Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли.
А вы как думаете — какой код можно назвать "серъёзным" или "сложным"? Как Вы вообще — разделяете ли код по каким-либо критериям и на какие то категории? И если да, то по каким?
Некоторые уже упоминались. Например "лохокод"
Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей. Какой нибудь навороченый алгоритм, с кучей условий (какая нибудь сложная сортировка или шифрование) — код сложный (алгоритмически), но тем не менее к серьёзному я его не отношу. По тем же причинам к серъёзному коду не отношу большинство модулей ОС, так как на мой взгляд — это код специфический — который должен быть написан крайне аккуратно и хорошо продуман, но чего-либо принципиально сложного в нем нет.
Наверняка у каждого из нас своя точка зрения по этому поводу. Предлагаю поделиться...
AF> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
Это хреновый код который не поддается пониманию и рефакторингу, такой код обычно выбрасывается на помойку после ухода программиста, писавшего его.
AF> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей. Какой нибудь навороченый алгоритм, с кучей условий (какая нибудь сложная сортировка или шифрование) — код сложный (алгоритмически), но тем не менее к серьёзному я его не отношу.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, AndreyFedotov, Вы писали:
AF>> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"?
IT>Не знаю какой код можно назвать "серьёзным", но вот "пальцастым" называется код, который пишут только настоящие пацаны
А какой код пишут "настоящие пацаны"? Кстати на чём? С? С++? C#? Ещё что то более пацанское?
Здравствуйте, Denwer, Вы писали:
D>Здравствуйте, AndreyFedotov, Вы писали:
AF>> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
D>Это хреновый код который не поддается пониманию и рефакторингу, такой код обычно выбрасывается на помойку после ухода программиста, писавшего его.
Это если код слишком сложен и содержит слишком много зависимостей, по сравнению с тем, что требуется для решения поставленной задачи. А если сама задача очень сложна? Экспертная система? Серврер БД? ERP система?
Здравствуйте, AndreyFedotov, Вы писали:
AF> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"?
Наверное,
серъёзный код — это код, за который дают серьезные деньги. Весь остальной код — несерьезен, за него дают или мало, или вообще ничего.
сложный код — это код, который не может быть написан программистом ниже определенного уровня. Весь остальной код — несложен, его пишет или любой новичок, или никто не пишет.
Здравствуйте, Vi2, Вы писали:
Vi2>Здравствуйте, AndreyFedotov, Вы писали:
AF>> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"?
Vi2>Наверное,
Vi2>серъёзный код — это код, за который дают серьезные деньги. Весь остальной код — несерьезен, за него дают или мало, или вообще ничего.
Гениально! Мне очень понравилось.
Vi2>сложный код — это код, который не может быть написан программистом ниже определенного уровня. Весь остальной код — несложен, его пишет или любой новичок, или никто не пишет.
Логично...
"Конечно, все вышесказанное относится к большим промышленным проектам, где объем кода измеряется миллионами и десятками миллионов строк и над которым работает хотя бы человек 50. К софту класса "t.c" длиной в 100 строк это не относится -- это можно писать на любом языке программирования."
Здравствуйте, AndreyFedotov, Вы писали:
Vi2>>серъёзный код — это код, за который дают серьезные деньги. Весь остальной код — несерьезен, за него дают или мало, или вообще ничего. AF> Гениально! Мне очень понравилось.
Тогда получается, что российские программисты пишут не серьёзный код. Зато американские всегда серьёзный, даже индусы и китайцы
... << Rsdn@Home 1.1.4 beta 1 >>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, AndreyFedotov, Вы писали:
Vi2>>>серъёзный код — это код, за который дают серьезные деньги. Весь остальной код — несерьезен, за него дают или мало, или вообще ничего. AF>> Гениально! Мне очень понравилось.
IT>Тогда получается, что российские программисты пишут не серьёзный код. Зато американские всегда серьёзный, даже индусы и китайцы
В общем то — отчасти — наверное да...
Но вообще то я больше иронизировал. Просто хочется что бы написание кода щедро финансировалось...
Я прекрасно понимаю, что одни в ящике за 3000р операционку реального времени ваяют, а другие, за $1200 кнопку на VB с грехом пополам прикручивают...
Здравствуйте, adb, Вы писали:
adb>Здравствуйте, AndreyFedotov, Вы писали:
adb>Там ведь было сказано:
adb>"Конечно, все вышесказанное относится к большим промышленным проектам, где объем кода измеряется миллионами и десятками миллионов строк и над которым работает хотя бы человек 50. К софту класса "t.c" длиной в 100 строк это не относится -- это можно писать на любом языке программирования."
Полностью согласен. Но по-моему это вполне очевидно. Ну не может быть код в 1-2-3 строки серьёзным...
Но и в больших промышленных проектах — код то же быват разный...
AF> Полностью согласен. Но по-моему это вполне очевидно. Ну не может быть код в 1-2-3 строки серьёзным... AF> Но и в больших промышленных проектах — код то же быват разный...
Если вы заметите, то упоминание "серъезного кода" было только в сабже. В тексте же речь шла только о "серъезных проектах".На лицо несоответствие сабжа с содержанием.
Здравствуйте, adb, Вы писали:
AF>> Полностью согласен. Но по-моему это вполне очевидно. Ну не может быть код в 1-2-3 строки серьёзным... AF>> Но и в больших промышленных проектах — код то же быват разный...
adb>Если вы заметите, то упоминание "серъезного кода" было только в сабже. В тексте же речь шла только о "серъезных проектах".На лицо несоответствие сабжа с содержанием.
Согласен. Тогда какие проекты Вы считаете серъёзными, а какие — нет?
AF> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"?
Серьезный код — код, важный по содержанию, требующий пристального внимания; ошибки в котором могут привести к опасным последствиям.
С данной точки зрения даже простейший внешне код, являющийся частью системы управления атомным реактором или системой жизнеобеспечения в реанимации — серьезен (можно вспомнить Саттера с его 23 вариантами выполнения четырех строк внешне "несерьезного" кода).
AF>для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
А вот это бы я назвал именно сложным кодом.
AF> Наверняка у каждого из нас своя точка зрения по этому поводу.
Я придерживался не только "точкой зрения", но и значением слов "серьезный" и "сложный" в литературном русском языке.
Но есть и еще одно определение:
Серьезный код — код, который не вызывает приступов истерического смеха у серьезного программиста. (Желающие дать определение термину "серьезный программист" — welcome во флейм или юмор).
Все, что здесь сказано, может и будет использоваться против меня...
Здравствуйте, Alex Reyst, Вы писали:
AF>> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"?
AR>Серьезный код — код, важный по содержанию, требующий пристального внимания; ошибки в котором могут привести к опасным последствиям. AR>С данной точки зрения даже простейший внешне код, являющийся частью системы управления атомным реактором или системой жизнеобеспечения в реанимации — серьезен (можно вспомнить Саттера с его 23 вариантами выполнения четырех строк внешне "несерьезного" кода).
Что же, на мой взгляд, очень разумно.
AF>>для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
AR>А вот это бы я назвал именно сложным кодом.
Иногда да, иногда нет. В таких системах часто сам код очень простой, но именно наличие множества скрытых и не очевидных связей делает его написание делом не простым.
AF>> Наверняка у каждого из нас своя точка зрения по этому поводу.
AR>Я придерживался не только "точкой зрения", но и значением слов "серьезный" и "сложный" в литературном русском языке.
Есть ведь такое понятие как трактовка или сравнение... Для начинающего и Hello World — код сложный, для профи — код и в 5000 строк может быть очень простым. Потому то и интересно, кто и какими критериями пользуется...
AR>Но есть и еще одно определение:
AR>Серьезный код — код, который не вызывает приступов истерического смеха у серьезного программиста. (Желающие дать определение термину "серьезный программист" — welcome во флейм или юмор).
Ну насчёт "серьёзных программистов" это точно во флейм или юмор. Мы или умеем что то делать или нет.
Здравствуйте, AndreyFedotov, Вы писали:
AF> Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли. AF> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"? Как Вы вообще — разделяете ли код по каким-либо критериям и на какие то категории? И если да, то по каким?
Судя по теме "о применимости С++ в серьёзном коде" единственный серьёзный код — это машинный код, набранный переключателями на панели управления.
Никаких толстенных стандартов на язык программирования, так как описание команд процессора умещается в тонкой книжке.
BTW, интеловский процессор не может исполнять серьёзный код, т.к. описание самого процессора занимает 3 тома.
Если серьёзно (сорри за каламбур), то серьёзный код — это миф, призванный удовлетворить самомнение пишушего его программиста.
Программа — это способ решить те или иные задачи. Если она написана в соответствии с требованиями, с заданным качеством и в срок, то IMHO без разницы, на каком языке написан код и как он выглядит (даже если это будет write-only код).
А _сложным_ может быть алгоритм, но не реализующий его код.
AF>>>для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
AR>>А вот это бы я назвал именно сложным кодом.
AF> Иногда да, иногда нет. В таких системах часто сам код очень простой, но именно наличие множества скрытых и не очевидных связей делает его написание делом не простым.
Интересно, как это код "с множеством связей... зависимостей... сложной архитектурой..." может быть простым?
Он может быть легким в разработке, но легкость не есть синоним простоты...
Все, что здесь сказано, может и будет использоваться против меня...
Здравствуйте, DarkGray, Вы писали: AR>>Интересно, как это код "с множеством связей... зависимостей... сложной архитектурой..." может быть простым? DG>Простой в том смысле, что каждый отдельный модуль, класс пишется тривиально, но вот организация всего этого в единую систему требует серьезных усилий
Именно. Большая система из простых элементов "по определению" является сложной системой. И ее "организация" ни в коем случае не является тривиальной и/или простой задачей. Или это уже "мелочи"?
Назвать такой код простым — все равно что назвать простым любой код, ибо любой код состоит из "организованного множества" "простых" элементов языка и API.
Все, что здесь сказано, может и будет использоваться против меня...
Здравствуйте, Vi2, Вы писали:
Vi2>Здравствуйте, AndreyFedotov, Вы писали:
AF>> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"?
Vi2>Наверное,
Vi2>серъёзный код — это код, за который дают серьезные деньги. Весь остальной код — несерьезен, за него дают или мало, или вообще ничего.
Vi2>сложный код — это код, который не может быть написан программистом ниже определенного
уровня.
Сложность кода это его характеристика, которая вполне измерима математически и выражает простоту(сложность) его понимания, модификации, поддержки, вероятность наличия в нем ошибок, возможность и затраты на его тестирование и т.д.
Например http://www.sei.cmu.edu/str/descriptions/cyclomatic_body.html
Vi2>Весь остальной код — несложен, его пишет или любой новичок, или никто не пишет.
Как раз наоборот — программист выше определенного (и достаточно высокого) уровня будет писать максимально простой код
Здравствуйте, postmaster, Вы писали:
P>Здравствуйте, AndreyFedotov, Вы писали:
AF>> Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли. AF>> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"? Как Вы вообще — разделяете ли код по каким-либо критериям и на какие то категории? И если да, то по каким?
P>Судя по теме "о применимости С++ в серьёзном коде" единственный серьёзный код — это машинный код, набранный переключателями на панели управления. P>Никаких толстенных стандартов на язык программирования, так как описание команд процессора умещается в тонкой книжке. P>BTW, интеловский процессор не может исполнять серьёзный код, т.к. описание самого процессора занимает 3 тома. P>
То есть мы естественным образом приходим к распространённому среди микроэлектронщиков мнению, что интеловские процессоры — "не серьёзные", лоховские, а вот Альфа...
P>Если серьёзно (сорри за каламбур), то серьёзный код — это миф, призванный удовлетворить самомнение пишушего его программиста. P>Программа — это способ решить те или иные задачи. Если она написана в соответствии с требованиями, с заданным качеством и в срок, то IMHO без разницы, на каком языке написан код и как он выглядит (даже если это будет write-only код).
Если "серъёзный" код это способ самоутверждения, то это код, который пишут "серьёзные" программисты.
Тем не менее бывает код очевидный, простой, который легко менять и это обходится без последствий, а есть такой код, который может и выглядит даже проще, но его изменение потруднее разгадывания кросворда....
P>А _сложным_ может быть алгоритм, но не реализующий его код.
Здравствуйте, AndreyFedotov, Вы писали:
AF> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей. Какой нибудь навороченый алгоритм, с кучей условий (какая нибудь сложная сортировка или шифрование) — код сложный (алгоритмически), но тем не менее к серьёзному я его не отношу. По тем же причинам к серъёзному коду не отношу большинство модулей ОС, так как на мой взгляд — это код специфический — который должен быть написан крайне аккуратно и хорошо продуман, но чего-либо принципиально сложного в нем нет.
типа вот . Супер простой код без взаимосвязей. Ну уж очень большой .
Здравствуйте, aka50, Вы писали:
A>Здравствуйте, AndreyFedotov, Вы писали:
AF>> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей. Какой нибудь навороченый алгоритм, с кучей условий (какая нибудь сложная сортировка или шифрование) — код сложный (алгоритмически), но тем не менее к серьёзному я его не отношу. По тем же причинам к серъёзному коду не отношу большинство модулей ОС, так как на мой взгляд — это код специфический — который должен быть написан крайне аккуратно и хорошо продуман, но чего-либо принципиально сложного в нем нет.
A>типа вот . Супер простой код без взаимосвязей. Ну уж очень большой .
A>http://kernelmapper.osdn.com/map.php
Если ты ещё и сам это написал — то ты просто ДЖЕДАЙ! Однозначно...
А если серъёзно — выглядит пугающе, но интересно — дело тут в коде или в его представлении? Можно умеючи такие диаграммы для простейшего кода начертить, что страшно станет...
да не . Это линукс кернель... причем довольно древний... 2.2 кажется... мне просто показалось что это будет в тему .
AF> А если серъёзно — выглядит пугающе, но интересно — дело тут в коде или в его представлении? Можно умеючи такие диаграммы для простейшего кода начертить, что страшно станет...
Скорее всего в прдеставлении... но и в коде тоже. Линукс (особенно ранние версии) написан "как курица лапой". Правда щас его причесывают помаленьку.
Здравствуйте, Vi2, Вы писали:
Vi2>серъёзный код — это код, за который дают серьезные деньги. Весь остальной код — несерьезен, за него дают или мало, или вообще ничего.
Супер!
Vi2>сложный код — это код, который не может быть написан программистом ниже определенного уровня. Весь остальной код — несложен, его пишет или любой новичок, или никто не пишет.
Мне кажется, что как-раз новичек горазд сложный код писать. А вот умудренных ж/опытом седой девелопер напишет как можно проще (в разумных пределах). Сложность — она диктуется обстоятельствами, но вообще не приветствуется.
Программист серъезного уровня — это такой программист, который напишет простой код там, где вьюноша как-раз обязательно нагромоздит вавилон с висячими садами камней.
ИМХО, серъезный код — это код докучи удовлетворяющий требованиям собственно к коду (эффективность, читаемость и т.п.). Сложность — не показатель.
Здравствуйте, _Obelisk_, Вы писали:
_O_>Здравствуйте, AndreyFedotov, Вы писали: AF>> А какой код пишут "настоящие пацаны"? Кстати на чём? С? С++? C#? Ещё что то более пацанское? _O_>ASM процессора Z80.
О! настальгия... между прочим асм там был ничего. даже недокументированные команды были! И какие!
а вообще серьезный код — это который взаимодействует с большим количеством сторонних компонент и библиотек. чер серьезней компоненты/библиотеки — тем серьезней код который с ними взаимодействует
Здравствуйте, ArtDenis, Вы писали:
AD>Здравствуйте, aka50, Вы писали:
A>>типа вот . Супер простой код без взаимосвязей. Ну уж очень большой . A>>http://kernelmapper.osdn.com/map.php
AD>Ага, захотел нас напугать фракталами?
Ты имеешь в виду, что серъёзный код это тот, которым можно людей пугать?
Здравствуйте, IT, Вы писали:
IT>Тогда получается, что российские программисты пишут не серьёзный код. Зато американские всегда серьёзный, даже индусы и китайцы
Вчера наблюдал результат творчества программистов Адобы (ИндизайнЦС). Я бы этих уродов выгнал бы на улицу. Не, лучше отправить в китай или индию. Большего они не стоят.
... << RSDN@Home 1.1.4 beta 1 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Astaroth, Вы писали:
AR>>(можно вспомнить Саттера с его 23 вариантами выполнения четырех строк внешне "несерьезного" кода).
A>Кого вспомнить?
Такие имена нужно знать, как Маркса/Энгельса
A>Можно линк?
На главной странице сайта есть ссылка "Поиск".
Пользуйся! (Рекомендация лучших поисководов!)
Здравствуйте, VladD2, Вы писали: VD>Вчера наблюдал результат творчества программистов Адобы (ИндизайнЦС). Я бы этих уродов выгнал бы на улицу. Не, лучше отправить в китай или индию. Большего они не стоят.
А еще при отладке плагинов под Адобы заметно, что там есть собранный в дебаге код
Здравствуйте, AndrewVK, Вы писали:
IT>>Не знаю какой код можно назвать "серьёзным", но вот "пальцастым" называется код, который пишут только настоящие пацаны
AVK>Пальцаны?
Ну да. Иногда среди них встречаются "паскальцаны".
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, AndreyFedotov, Вы писали:
AF> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей. Какой нибудь навороченый алгоритм, с кучей условий (какая нибудь сложная сортировка или шифрование) — код сложный (алгоритмически), но тем не менее к серьёзному я его не отношу. По тем же причинам к серъёзному коду не отношу большинство модулей ОС, так как на мой взгляд — это код специфический — который должен быть написан крайне аккуратно и хорошо продуман, но чего-либо принципиально сложного в нем нет. AF> Наверняка у каждого из нас своя точка зрения по этому поводу. Предлагаю поделиться...
ты сам ответил на свой вопрос (выделено жирным). я бы только эти два утверждения местами поменял, т.к. нужно сначала (про)думать, а потом делать.
--
DSD
Re: Пример не серьезного и аналогичного ему серьезного кода
Здравствуйте, AndreyFedotov, Вы писали:
AF> Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли. AF> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"? Как Вы вообще — разделяете ли код по каким-либо критериям и на какие то категории? И если да, то по каким?
Я склоняюсь к мысли, что "серьезность" кода больше определяется его назначением, областью применения и т.п., нежели непосредственно его содержанием, например:
Делаем форму, кидаем не нее кучу контролов разных навороченных и делаем какую-нить процедуру отображения даных из БД на эту форму.
"Серьезный" код — если это используется в программе управления космическим кораблем или в программе управления биржевыми торгами.
Не "серьезный" код — все это написано для сдачи зачета в институте.
Другими словами, можно сказать, что чем больше отвественность лежит на коде, тем "серьезнее" код.
"Сложность" кода — это исходя их каких параметров оценки смотреть: сложность понимания, кодирования, поддержки, модификации и т.п.
З.Ы. Сложнее всего написать простой код -> "сложный" код — это есть простой код
Здравствуйте, AndreyFedotov, Вы писали:
AF> Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли.
Правильно сказали что есть разница между серьезным и сложным. Серьезность кода это серьезности задачи, а серьезность задачи вообще управленческая область.
Про сложность и классификации . Если не брать в расчет предметную область, то тогда получается 2 измерения: слабая/сильная детерминированность, слабая/сильная абстрактность. Хотя может показаться что это что-то близкое, я думаю что нет. Если же взять еще и предметную область (живем же в реальном мире), то тогда 3 измерение — специфичность этой области.
Про детерминированность хочеться сказать то, что чем она больше, тем ближе к машине (скорость, память...) но зато и дальше от человека. При всем при том что и сильная и слабая может писаться на одном языке, сильная выглядит страшнее ассемблера. Выбрасываются строки, там где это можно, всякие универсальные коллекции заменяются типизированными или массивами, красивое с точки зрения дизайна заменяется на некрасивое но производительное. Такая вот селяви.
Здравствуйте, Alex Reyst, Вы писали:
AR>Серьезный код — код, который не вызывает приступов истерического смеха у серьезного программиста. (Желающие дать определение термину "серьезный программист" — welcome во флейм или юмор).
Не знаю, могу ли я считать себя серьезным программистом, но однажды мне принесли код и я буквально чуть не помер от смеха. Подозвал коллег, и они тоже чуть не уписались. Код был очень несерьезный
Здравствуйте, AndreyFedotov, Вы писали:
AF>>>для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
AR>>А вот это бы я назвал именно сложным кодом.
AF> Иногда да, иногда нет. В таких системах часто сам код очень простой, но именно наличие множества скрытых и не очевидных связей делает его написание делом не простым.
Может просто проблема проектирования? Код должен быть простым для понимания, тогда это хороший код. Смотря, конечно, для кого простым На асме писать очень просто, но при сложном алгоритме (да и просто по мере разбухания проекта, если его правильно не спроектировать) получается как раз такой "серьезный", по-твоему определению, код. На ЯВУ же этого запутывания имхо можно избежать.
Re[2]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, shev, Вы писали:
S>В данном серьезном коде допущена серьезная ошибка. Создание объекта TIniFile должно быть вынесено из блока try..finally
Да что Вы такое говорите! Да неужели? Правда что ли??? А если подумать?
А что если допустить такую крамольную мысль, что исключительная ситуация может быть возбуждена внутри конструктора или даже перед конструированием (память кончилась), тогда что?
Код:
f := NIL;
TRY
f := TMyObject.Create(SomeObj.GetParameters());
f.DoSmth();
FINALLY
f.Free();
END;
остается безопасным в обоих случаях:
1) Объект еще не успел создаться, т.е. f = NIL (это из-за того что Free перед вызовом деструктора проверяет Self на равенство NIL),
2) Объект уже успел создаться — в FINALLY уничтожаем его
Re[4]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>А что если допустить такую крамольную мысль, что исключительная ситуация может быть возбуждена внутри конструктора или даже перед конструированием (память кончилась), тогда что?
Тогда объект TMyObject не создастся и освобождать объект методом Free() не требуется. Произойдет обычное прерывание из-за произошедшего исключения.
SYG>1) Объект еще не успел создаться, т.е. f = NIL (это из-за того что Free перед вызовом деструктора проверяет Self на равенство NIL), SYG>2) Объект уже успел создаться — в FINALLY уничтожаем его
Общий принцип работы с исключениями:
obj := TMyObject.Create();
//создаем объект, если в процессе создания произошло исключение (объект не создастся), то
//просто вывалимся до ближайшей обработки исключения верхнего уровня. try//что-то делаем с объектом obj, что может вызвать иcключениеfinally
obj.free;
//освобождаем объект и опять же вываливаемся до ближайшей обработки исключения верхнего уровняend
Конечно, Ваш вариант абсолютно работоспособен и я поспешил утверждать что он содержит серьезную ошибку, т.к. как Вы уже написали выше "Free перед вызовом деструктора проверяет Self на равенство NIL".
Хотя...
Пришла мысль. Вот код, в котором Вас стиль использования исключений будет неправильным, и даже приведет к серьезной ошибке, которую не так очевидно будет обнаружить:
TMyClass=class(TObject)
public
constructor Create(OpenFileName: string);
end;
procedure OpenManyFiles(ListFiles: TList);
var
obj: TMyClass;
begin
try
obj:=TMyClass.Create('FirstFileName');
ListFiles.Add(obj);
finally
obj.Free;
end;
try
obj:=TMyClass.Create('SecondFileName');
ListFiles.Add(obj);
finally
obj.Free;
end;
end;
Процедура OpenManyFiles открывает несколько файлов и сохранят объекты их обслуживающие в списке файлов ListFiles.
Возьмем случай, когда открытие первого файла прошло успешно, а второго 'SecondFileName' нет.
Тогда obj до вызова конструктора
obj:=TMyClass.Create('SecondFileName');
будет содержать ссылку на первый файл. Когда произойдет исключение, то в блоке finally вызовется метод Free для obj первого файла!, ссылка на который уже давно лежит в списке ListFiles и в последствии будет использоваться другим кодом. Т.е. новая ошибка затаится до момента, когда кто-то захочет пробежаться по элементам списка ListFiles. А наступить это может через большой промежуток времени, в абсолютно далеком месте программы и найти концы будет очень сложно.
Конечно можно избежать данной ситуации, если между открытиями первого и второго файла дописать obj:=nil, но это можно забыть сделать.
В случае же если создание объекта вынесено из блока try..finally (всегда считал это классическим способом), описанной выше проблемы просто не произойдет. И такой способ является абсолютно безопасным.
Re[5]: Пример не серьезного и аналогичного ему серьезного ко
Я согласен с Вами в том, что код, который я привел
f := NIL;
TRY
f := TMyObject.Create();
//...FINALLY
f.Free;
END;
действительно может содержать грубейшую ошибку, но только в том случае если забыть написать инструкцию f := NIL. Постольку поскольку, я ее написать не забыл, то приведенный код не содержит ошибки. Что Вы накинулись -"Ошибка, Ошибка!!". Нет ошибки-то. О чем весь сыр бор? Может закончим на этом?
Я могу объяснить почему я использую именно такую конструкцию. Поначалу я тоже писал TRY после, а не до создания объекта, но потом перешел на этот стиль потому что, часто создаю несколько объектов (бывает даже по 10-15 штук):
a := NIL; b := NIL; c := NIL;
TRY
a := TAaa.Create();
b := TBbb.Create();
c := TCcc.Create();
//...совместное использование объектов a,b,cFINALLY
a.Free; b.Free; c.Free;
END;
Если бы я писал TRY после, то пришлось бы вкладывать блоки TRY FINALLY друг в друга:
a := TAaa.Create();
TRY
b := TBbb.Create();
TRY
c := TCcc.Create();
TRY//...совместное использование объектов a,b,cFINALLY
c.Free;
END;
FINALLY
b.Free;
END;
FINALLY
a.Free;
END;
код от этого раздувается, поэтому я так и не пишу, а пишу так как показал в самом начале.
Re[6]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, AndreyFedotov, Вы писали:
AF> Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли. AF> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"? Как Вы вообще — разделяете ли код по каким-либо критериям и на какие то категории? И если да, то по каким? AF> Наверняка у каждого из нас своя точка зрения по этому поводу. Предлагаю поделиться...
Серьезный код — это код, который делается не дял себя. Например, диплом. Это уже серьезно, так как диплом надо защищать и демонстрировать работоспособность системы. Если вы мне скажете, что диплом никто не читает, так вы ошибетесь — я читаю.
В общем, серьезный код — это код, оттогаемый от разработчика и используемый другими людьми.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, AndreyFedotov, Вы писали:
AF>> Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли. AF>> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"? Как Вы вообще — разделяете ли код по каким-либо критериям и на какие то категории? И если да, то по каким? AF>> Наверняка у каждого из нас своя точка зрения по этому поводу. Предлагаю поделиться... LVV>Серьезный код — это код, который делается не дял себя. Например, диплом. Это уже серьезно, так как диплом надо защищать и демонстрировать работоспособность системы. Если вы мне скажете, что диплом никто не читает, так вы ошибетесь — я читаю. LVV>В общем, серьезный код — это код, оттогаемый от разработчика и используемый другими людьми.
Серьезность кода и диплом не имееют ничего общего, по крайней мере везде где я знаю так оно и есть. Я знаю такие дипломные работы, котрые даже на лабораторную для 1-ого курса не потянут. А код которых и глядеть страшно.
ЗЫ: Исключения бывают конечно, но это именно исключения, а не правила.
Re[7]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, S.Yu.Gubanov, Вы писали:
WH>Кстати классный пример того почему С++ рулит... WH>
WH>Taaa a;
WH>Tbbb b;
WH>Tccc c;
WH>...
WH>
WH>
Ну это быстренько можно "подпортить", и "рульность" С++ поубавится
1) Пусть a,b,c — это очень большие объекты, так что на стеке втроем им места не хватит...
2) Пусть a,b,c — это не объекты, а полиморфные переменные. В терминологии С++ статический тип a,b,c — пусть будет указатели на объекты "абстрактных классов". Так как в стандартном С++ есть только блок try catch, а FINALLY — нету, то жизнь сразу усложняется. Придется использовать классы обертки — "умные указатели", а это уже из другой оперы.
Здравствуйте, Denwer, Вы писали:
D>Серьезность кода и диплом не имееют ничего общего, по крайней мере везде где я знаю так оно и есть. Я знаю такие дипломные работы, котрые даже на лабораторную для 1-ого курса не потянут. А код которых и глядеть страшно.
D>ЗЫ: Исключения бывают конечно, но это именно исключения, а не правила.
Ну так у нас сплошные исключения
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[8]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Придется использовать классы обертки — "умные указатели", а это уже из другой оперы.
Ну почемуже из другой оперы? Очень даже из тойже самой... Автоматические деструкторы рулят
Затараты памяти и производительность не изменятся.
Хотя я обычно использую объекты с интрузивным подсчетом ссылок.
SYG>Вот уж кто в таких случаях на самом деле по взрослому рулит, так это (компилируемый) язык со сборщиком мусора и без "исключительных ситуаций", например, Component Pascal (http://www.inr.ac.ru/~info21/cpascal/cp_report_1.4_rus.htm)
Практика показывает что очень часто от ГЦ поблем больше чем пользы. Тк время уничтожения объекта недетерминировано то возникает проблема с освобожедением внешних ресурсов.
А отсутствие исключений это гемор тот еще... Попробуй вернуть ошибку на 10 уровней наверх без исключений...
Короче мертворожденный продукт. Он не сможет конкурировать ни С++ на полу С++ ни с .НЕТ на полу .НЕТ. Ибо и тому и другому проигрывает по возможностям. Накой это язык вобще нужен не понятно.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, WolfHound, Вы писали:
WH>Практика показывает что очень часто от ГЦ поблем больше чем пользы. Тк время уничтожения объекта недетерминировано то возникает проблема с освобожедением внешних ресурсов.
Какие проблемы?
WH>А отсутствие исключений это гемор тот еще... Попробуй вернуть ошибку на 10 уровней наверх без исключений...
Зачем возвращать ошибку?
WH>Короче мертворожденный продукт. Он не сможет конкурировать ни С++ на полу С++ ни с .НЕТ на полу .НЕТ. Ибо и тому и другому проигрывает по возможностям. Накой это язык вобще нужен не понятно.
Странный Вы. Component Pascal-ю более 10 лет между прочим.
Просто когда есть Сборщик мусора, проектировать все надо совершенно по другому, а это как-то непривычно.
Мысли на счет исключений:
Исключения бывают "вредные" — то есть те которые и быть-то не должны — они сигнализируют о сбое работы программы, если они возникают, значит программа написана криво; а бывают "полезные" — это те исключения, которых ожидают и обрабатывают согласно логике работы программы, они заранее были запланированы. Так вот в Component Pascal так сказать "вредные" исключения (выход индекса за пределы массива, неправильное приведение типа, не предусмотренный вариант выбора в инструкции CASE и т.п.) — просто автоматически немедленно останавливают работу программы и все — программиста на мыло! А все "полезные" исключения всегда можно реализовать вовсе каким-нибудь другим способом, а не через собственно механизм исключений, если подумать конечно. Так что механизм исключений излишен.
Re[10]: Пример не серьезного и аналогичного ему серьезного к
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Какие проблемы?
Открыли фаил, поработали и забыли, открыли еще один фаил поработали и забыли... тк время уборки мусора недетерминировано открытых файлов скопится может очень много... и не исключен вариант что у системы закончатся лимит открытых файлов и все...
Вот только не надо мне втирать что я должен помнить о том что я открыл фаил... Во первых я ни кому ни чего не должен, во вторых я человек и могу забыть, в третьих любимый тобой С++ помнит это за меня.
SYG>Зачем возвращать ошибку?
А что мне делать если пользователь ввел не верные данные?
SYG>Странный Вы. Component Pascal-ю более 10 лет между прочим.
Если он такой крутой и ему уже 10 лет то почему на нем никто не пишет?
SYG>Мысли на счет исключений:
Во первых о вредных исключениях надо расказать все что можно для того чтобы было легче устранить ошибку.
Во вторых на кой черт извращатся если можно кинуть исключение?
Мне влом выписывать и еще болие влом читать что-то типа:
А если логика алгоритма сложная то за обработкой ошибок с которыми на этом уровне всеравно ни чего не сделать можно потерять сам алгоритм.
А если еще учесть что исключения это классы, а их можно наследовать то допустим мы можем сделать file_exception и отнаследовать от него open_file_exception, read_file_exception... теперь нам фиолетово какое именно из этих исключений вылетело мы их все можем поймать при помощи catch(file_exception const& ex). А теперь сделай тоже самое на кодах возврата.
И самое веселое если в некоторой подсистеме может происходить несколько типов ошибок (проблемы с файлами, сетью, пользователем...) что ты тогда будешь делать с кодами возврата?
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: Пример не серьезного и аналогичного ему серьезного к
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Мысли на счет исключений: SYG>Исключения бывают "вредные" — то есть те которые и быть-то не должны — они сигнализируют о сбое работы программы, если они возникают, значит программа написана криво; а бывают "полезные" — это те исключения, которых ожидают и обрабатывают согласно логике работы программы, они заранее были запланированы. Так вот в Component Pascal так сказать "вредные" исключения (выход индекса за пределы массива, неправильное приведение типа, не предусмотренный вариант выбора в инструкции CASE и т.п.) — просто автоматически немедленно останавливают работу программы и все — программиста на мыло!
Не, "автоматически немедленно" останавливать работу программы это полумера. Надо, чтобы она сама себя тут же и деинсталлировала и возвращала пользователю уплаченные за себя деньги, после чего "автоматически" коннектилась к сайту разработчиков и отправляла "на мыло" провинившегося программиста по имени "Component Pascal"
Здравствуйте, WolfHound, Вы писали:
WH>Открыли фаил, поработали и забыли, открыли еще один фаил поработали и забыли... тк время уборки мусора недетерминировано открытых файлов скопится может очень много... и не исключен вариант что у системы закончатся лимит открытых файлов и все... WH>Вот только не надо мне втирать что я должен помнить о том что я открыл фаил... Во первых я ни кому ни чего не должен, во вторых я человек и могу забыть, в третьих любимый тобой С++ помнит это за меня.
Можно поконкретнее? Что конкретно обозначают слова "забыли" и "помнит это за меня"? А то просто нету предмета для обсуждения.
WH>А что мне делать если пользователь ввел не верные данные?
Это вопрос по программированию или по какой теме? Наверное, в таких случаях надо:
1) Уж точно даже не пытаться работать с неверными данными.
2) Как можно скорее сообщить об этом пользователю, если это возможно.
3) Если пользователь не в состоянии быстро ответить, то перейти к выполнению какой-нибудь другой задачи, чтобы время не терять.
SYG>>Странный Вы. Component Pascal-ю более 10 лет между прочим. WH>Если он такой крутой и ему уже 10 лет то почему на нем никто не пишет?
Я сам на работе на нем не пишу, но слышал, что есть такие конторы где пишут на оберонах (в основном для космоса, для беспилотных летательных аппаратов, электростанций и тому подобных вещей).
WH>А если еще учесть что исключения это классы, а их можно наследовать то допустим мы можем сделать file_exception и отнаследовать от него open_file_exception, read_file_exception... теперь нам фиолетово какое именно из этих исключений вылетело мы их все можем поймать при помощи catch(file_exception const& ex). А теперь сделай тоже самое на кодах возврата.
Во-первых, если Вам обязательно надо что-то возвращать, то ни кто не заставляет Вас возвращать именно номер_кода_ошибки. Возвращайте пожалуйста полиморфную переменную внутри которой инкапсулирована информация о причине отказа выполнить операцию — то есть все так же как и при механизме исключений — "фиолетово". Сборщик мусора поможет Вам не беспокоится о возможной растрате памяти на эти полиморфные переменные.
Во-вторых, Вы не обязаны что-то возвращать. Если Вам известно что какая-то операция потенциально опасна, то прежде чем ее выполнять, Вы "морально обязаны" проверить правильность параметров (проверить индекс массива на попадание в нужный диапазон, проверить указатель на неравенство NIL, проверить динамический тип полиморфной переменной, проверить не получится ли у Вас арифметическое переполнение, деление на ноль и т.д.) и только после того как Вы убедились в том, что данные правильные, вот только после этого приступать к выполнению потенциально опасной операции. Если в этом случае эта операция все-равно провалится, то поскольку согласно логике программы данные правильные и никакой ошибки быть не должно — это означает, что причина ошибки находится вне логики программы (кто-то отцепил жесткий диск, повредил молотком процессор и т.п.), следовательно дальнейшее выполнение программы не имеет смысла.
Вы можете возразить, что существуют некоторые потенциально опасные операции, перед выполнением которых невозможно точно знать смогут ли они быть выполнены или нет. Никакая проверка данных не может дать ответа на вопрос о том возможно ли выполнение этой операции. И вот именно в этих случаях без механизма исключительных ситуаций обойтись нельзя. Я принимаю такое возражение, соглашаюсь с ним. Однако давайте попробуем перечислить примеры таких операций:
1) Разыменование указателя не равного NIL.
2) "Насильное" приведение типов.
Подробно:
1) Никогда нельзя знать "повис" указатель или нет. Никакая проверка не может ответить на этот вопрос. Разыменование указателя — это рискованная операция. Нам остается только помолится и попробовать это сделать, в случае неудачи будет возбуждена исключительная ситуация, мы ее обработаем и все будет чики-пуки! Однако есть альтернатива — Сборщик мусора. Если в языке есть сборщик мусора, то в программе никогда не будет повисших указателей. Проблема решена. Разыменование указателя не равного NIL — абсолютно безопасна.
2) Надо всего лишь запретить "насильное" приведение типов. Точно так же как в свое время запретили инструкцию goto. Проблема решена. Разрешенные динамические преобразования типов абсолютно безопасны.
Если Вам известны еще примеры потенциально опасных операций правильный исход которых заранее проверить невозможно, то пишите, обсудим.
Здравствуйте, AndreyFedotov, Вы писали:
AF>>> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
D>>Это хреновый код который не поддается пониманию и рефакторингу, такой код обычно выбрасывается на помойку после ухода программиста, писавшего его.
AF> Это если код слишком сложен и содержит слишком много зависимостей, по сравнению с тем, что требуется для решения поставленной задачи. А если сама задача очень сложна? Экспертная система? Серврер БД? ERP система?
Тогда на помойку выбрасывается фирма, после ухода этого программиста.
Здравствуйте, Candle645, Вы писали:
C>Как раз наоборот — программист выше определенного (и достаточно высокого) уровня будет писать максимально простой код
немного не так...
максимально простой и логичный по сравнению с новичком, и только в том случае, когда задача и новичку под силу...
Re[12]: Пример не серьезного и аналогичного ему серьезного к
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Можно поконкретнее? Что конкретно обозначают слова "забыли" и "помнит это за меня"? А то просто нету предмета для обсуждения.
Пример на C#
если забыть сделать file.Close() то фаил не будет закрыт до сборки мусора.
В С++
std::fstream file("some.file");
file.close();
file.close() делать не обязательно ибо фиал будет закрыт в деструкторе fstream при выходе переменной file из области видимости.
SYG>1) Уж точно даже не пытаться работать с неверными данными.
Это точно. SYG>2) Как можно скорее сообщить об этом пользователю, если это возможно.
А как сообщить об этом пользователю? Допустим у меня есть некий очень сложный код который не знает в каком окружении он работает, а даже если бы и знал то пристовать к бользователю в обход того кода который взаимодействует с пользователем это бардак.
Дык вот вернуть ошибку из глубины этого кода без исключений довольно проблематично.
SYG>Я сам на работе на нем не пишу, но слышал, что есть такие конторы где пишут на оберонах (в основном для космоса, для беспилотных летательных аппаратов, электростанций и
Ты с Адой не путаешь? Даже если нет то по масштабу использования он в месте с Адой и рядом не стоял с С++.
Те за 10 лет ему удалось занять ничтожную часть производства ПО от сюда вывод...
SYG>Во-первых, если Вам обязательно надо что-то возвращать, то ни кто не заставляет Вас возвращать именно номер_кода_ошибки.
В любом случае этот код в силе Re[10]: Пример не серьезного и аналогичного ему серьезного к
SYG>Во-вторых, Вы не обязаны что-то возвращать. Если Вам известно что какая-то операция потенциально опасна, то прежде чем ее выполнять, Вы "морально обязаны" проверить правильность параметров
Вот это и есть исключительная ситуация. Дальше работать нельзя и надо с этим что-то делать, а сделать это внутри некоторого алгоритмы не реально тем болие что какправило не понятно что делать.
В этом случае спокойно кидаем исключение и пусть с ошибкой разбирается тот кто знает что с ней делать.
SYG>1) Никогда нельзя знать "повис" указатель или нет.
Поверь мне они у меня и без ГЦ никогда не появится ибо:
Предохраняйтесь смартпоинтерами и ваши указатели не будут висячими.
SYG>2) Надо всего лишь запретить "насильное" приведение типов.
Не надо. Иногда без него ни куда. Но такие штуки у нормальных людей спрятаны в библиотеку за дуракоустойчивым интерфейсом. SYG>Точно так же как в свое время запретили инструкцию goto.
Генерить парсер на конечном автомате без goto мягко говоря проблематично... SYG>Проблема решена.
Как всегда одни проблемы решены, а другие добавлены...
Причем опять же как всегда решены мифические, а добавлены вполне реальные.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[12]: Пример не серьезного и аналогичного ему серьезного к
SYG> Если в этом случае эта операция все-равно провалится, то поскольку согласно логике программы данные правильные и никакой ошибки быть не должно — это означает, что причина ошибки находится вне логики программы (кто-то отцепил жесткий диск, повредил молотком процессор и т.п.), следовательно дальнейшее выполнение программы не имеет смысла.
Вы почему-то априори считаете, что текущая выполняемая функция и вся программа — это одно и тоже, и из этого делаете вывод, что раз текущая функция не смогла выполниться, то значит надо закрывать всю программу.
Но для большинства задач — это не так.
Возьмем, например, браузер — коннект с сервером может быть в любой момент прерван, но весь браузер не должен закрываться.
Или возьмем, например, текстовый редактор и операцию сохранения файла на дискету: дискета может быть битая и операция сохранения не выполнится, но это опять же не означает, что весь текстовый редактор необходимо при этом закрывать.
Или возьмем графический редактор, который работает с множеством картинок и при загрузке очередной картинки вдруг выяснилось, что память кончилась — опять же бессмысленно закрывать весь граф. редактор
SYG>Если Вам известны еще примеры потенциально опасных операций правильный исход которых заранее проверить невозможно, то пишите, обсудим.
1. Выделение памяти
2. Любые операции с внешним миром: операции с диском, сетью, интернетом, пользователем, другими программами и т.д.
3. Для случая распределенной программы, вообще, любой вызов функции может закончится неудачей, т.к. может быть именно в этот момент пропала связь с удаленным модулем.
Re[13]: Сборщик мусора - это не роскошь, а осознанная необхо
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>Можно поконкретнее? Что конкретно обозначают слова "забыли" и "помнит это за меня"? А то просто нету предмета для обсуждения. WH>Пример на C# WH>
WH>file.close() делать не обязательно ибо фиал будет закрыт в деструкторе fstream при выходе переменной file из области видимости.
Это, мягко говоря, немного устаревший способ работы с файлами. Всвязи с появлением ООП, люди уже более десятка лет с файлами работают на более высоком уровне абстракции. Могу вкратце описать как это делается в системе BlackBox от Oberon Microsystems. В этой системе для этой цели используется паттерн проектирования под названием "Carrier-Rider-Mapper". Carrier — это персистентный объект содержащий внутри себя какие-либо данные (можно думать о нем как об объектно-ориентированном аналоге устаревшего понятия — "файл"). Для простоты примера давайте предположим, что речь идет о файле с текстом. Carrier — это персистентный объект внутри которого инкапсулирован текст. Доступ к этому тексту одновременно можно предоставить сразу нескольким клиентам, например, открыть несколько окон с одним и тем же содержимым. Каждый клиент должен, как минимум, знать в каком месте текста он в данный момент имеет "текущую позицию". Так как количество клиентов произвольное, то информация о текущей позиции не может хранится в самом объекте Carrier, для этих целей объект Carrier умеет создавать так называемые Rider-объекты (паттерн — "итератор"). Так что клиенты обращаются не на прямую к объекту Carrier, а посредством Rider-ов. Между Carrier-ом и Rider-ами существует отношение один-ко-многим. Аналогично Rider-ам объект Carrier может создавать объекты Writer-ы, которые умеют "писать", в отличие от "читающих" Rider-ов. На этом приключения не заканчиваются. Кроме Carrier, Rider-ов и Writer-ов существуют еще так называемые Mapper-ы. Дело в том что Rider-ы и Writer-ы представляют низкоуровневый интерфейс (теоретически, вплоть до: записать один байт, прочитать один байт). Mapper-ы — это объекты-прослойки между Rider-ами, Writer-ами и клиентами. Они предоставляют более высокоуровневый уже проблемно-ориентированный набор операций для чтения и записи. Разные приложения могут использовать разные Mapper-ы работая с одним и тем же Carrier-ом.
Вобщем, клиенты общаются с Carrier-ом даже не через Reader/Writer, а через Mapper-ы. Сами Reader/Writer-ы нужны для того чтобы предотвратить комбинаторный взрыв количества реализаций разных мапперов под разные кариеры. Если есть n-штук Carrier-ов и m-штук Mapper-ов, то в этом случае надо написать реализацию только для n+m полиморфных переменных, а вовсе не для n*m как могло бы быть без Reader/Writer-ов.
Теперь вернемся к Вашему вопросу о "забыть сделать file.Close() то фаил не будет закрыт до сборки мусора". Понимаете в чем дело-то, клиент понятия не имеет о том сколько еще других клиентов приконнекчено к Carrier-у, а значит клиент в принципе не может выполнить операцию file.Close(), в интерфейсах форматтеров, райдеров, врайтеров и карьеров такой операции нет по принципиальным причинам. Подконнекчиваясь к кариеру клиенту совершенно безразлично был ли это кариер только что создан (только что открыли файл) или он уже существовал (файл уже был открыт кем-то другим). Клиент получает в свое пользование Carrier-скую полиморфную переменную и делает с ней что хочет, а потом забывает о ней. Так же поступают другие клиенты. Сам же Carrier являясь персистентным объектом, всегда существует в единственном экземпляре, то есть Ваши опасения по забывчивости открыть несколько раз один и тот же файл совершенно напрасны (работает некоторая модификация паттерна Singleton).
Теперь, собственно, при чем тут сборщик мусора. Рассмотрим более общую ситуацию. Пусть есть многомодульная система. Большинство модулей на момент написания не имели никакого представления друг о друге. Модули — единицы компиляции и исполнения программы, они могут динамически загружаться/выгружаться во время работы Программы. Под Программой, можно понимать всю операционную систему, а модули — ее расширения. Модули создают внутри себя объекты и в виде полиморфных переменных передают их для использования другим модулям, те модули, в свою очередь, могут передать эти полиморфные переменные третьим модулям и т.д.. Модуль создавший обьект и отдавший его другому модулю в принципе понятия не имеет кто еще пользуется этим объектом и как долго он это намерен делать. А значит модуль-создатель в принципе не может нести ответсвенность за уничтожение им созданного объекта. Но никакой другой модуль тоже в принципе не может нести ответсвенность за уничтожение чужого объекта. Подсчет ссылок на объект проблемы не решает поскольку, в общем случае, возможны замкнутые петли (циклические) ссылки объектов друг на друга. Утечка памяти в многомодульных системах неизбежна по принципиально неразрешимым причинам. Единственным выходом из этой ситуации является наличие единого на всю операционную систему полноценного сборщика мусора. Сборщик мусора — это не роскошь, и не фича придуманная для ленивых программистов. Сборщик мусора — это осознанная необходимость. Существование многомодульныех систем, модули которых обмениваются друг с другом объектами, невозможно без одного на всех полноценного сборщика мусора.
//----------------------------------------
Паттерн Carrier-Rider-Mapper был получен в результате исследовательского проекта "Insight ETHOS: On Object-Orientation in Operating Systems" Clementh Szyperski; Zьrich, 1992. (также этот паттерн сейчас известен как "Bridge pattern" — это по классификации "Банды четырех" Гамма, Хелм, Джонсон, Влиссидес). Клеменс Шиперский — один из со-основателей компании Oberon Microsystems. Также он является основоположником КОП — компонентно ориентированного программирования. Его статья о том что такое КОП и почему одно лишь "голое" ООП само по себе не состоятельно, датируется кажется то-ли 1994, то-ли 1995 годом (под рукой нет, я ее засунул куда-то). Сейчас он работает в Микрософте, платформа .NET позаимствовала от ОС Оберон кое-что.
Re[13]: Внешнее не имеет непосредственной власти над внутрен
SYG>> Если в этом случае эта операция все-равно провалится, то поскольку согласно логике программы данные правильные и никакой ошибки быть не должно — это означает, что причина ошибки находится вне логики программы (кто-то отцепил жесткий диск, повредил молотком процессор и т.п.), следовательно дальнейшее выполнение программы не имеет смысла.
DG>Вы почему-то априори считаете, что текущая выполняемая функция и вся программа — это одно и тоже, и из этого делаете вывод, что раз текущая функция не смогла выполниться, то значит надо закрывать всю программу. DG>Но для большинства задач — это не так.
DG>Возьмем, например, браузер — коннект с сервером может быть в любой момент прерван, но весь браузер не должен закрываться.
DG>Или возьмем, например, текстовый редактор и операцию сохранения файла на дискету: дискета может быть битая и операция сохранения не выполнится, но это опять же не означает, что весь текстовый редактор необходимо при этом закрывать.
DG>Или возьмем графический редактор, который работает с множеством картинок и при загрузке очередной картинки вдруг выяснилось, что память кончилась — опять же бессмысленно закрывать весь граф. редактор
SYG>>Если Вам известны еще примеры потенциально опасных операций правильный исход которых заранее проверить невозможно, то пишите, обсудим.
DG>1. Выделение памяти DG>2. Любые операции с внешним миром: операции с диском, сетью, интернетом, пользователем, другими программами и т.д. DG>3. Для случая распределенной программы, вообще, любой вызов функции может закончится неудачей, т.к. может быть именно в этот момент пропала связь с удаленным модулем.
Видите ли, для начала надо просто понять одну простую вещь. Ничто внешнее по отношению к нашей программе ни при каких обстоятельствах никогда не может создать исключительную ситуацию здесь внутри нашей программы. Все что происходит внутри нашей программы делается только потому что программа так была написана. Ни что внешнее вообще понятия не имеет о внутренностях программы — в этом заключается принцип инкапсуляции. Вера в то что что-то внешнее способно само что-то сделать внутри программы сродни вере в целительную силу танцев с бубном. После того как мы поймем эту простую вещь наша дальнейшая жизнь будет значительно проще.
Теперь по пунктам. DG> 1. Выделение памяти
Выделение памяти для пользователей языка программирования является абсолютно безопасной операцией
NEW(p);
IF p # NIL THEN ... END;
Если памяти недостаточно, то процедура NEW() всего лишь навсего вернет пустой (NIL) указатель. Никаких исключительных ситуаций при этом не возникнет.
DG> 2. Любые операции с внешним миром: операции с диском, сетью, интернетом, пользователем, другими программами и т.д. DG> 3. Для случая распределенной программы, вообще, любой вызов функции может закончится неудачей, т.к. может быть именно в этот момент пропала связь с удаленным модулем.
Все эти операции абсолютно безопасны. Не читается дискета? — Великолепно, так и сообщим пользоваелю что не читается дискета, при чем здесь исключительная ситуация? Буфер порта TCP/IP протокола пустой — так и скажем пользователю что интернет упал. Где здесь исключение? Другая программа не отвечает — великолепно, не больно то и хотелось. Здесь нигде нет ни одной исключительной ситуации. Все ситуации — штатные, обычные, заранее известные.
Вам не удалось привести ни одного примера потенциально опасной операции чей фатальный исход невозможно предугадать заранее путем проверки входных данных. Примеры, которые Вы привели, абсолютно безопасны просто в случае неудачи, например, возвращают FALSE вместо TRUE, но исключительных ситуаций они при этом не создают. Вы перепутали операции которые не могут быть выполнены — то есть завершаются фатально (например возвращая FALSE), с операциями которые во время выполнения приводят к возникновению исключительных ситуаций. К потенциально опасным операциям относятся: деление на ноль и другие арифметические переполнения, неправильный индекс массива, разыменование повисшего указателя, и, быть может, что-то еще. Но вот что?
Здравствуйте, eugals, Вы писали:
E>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>Мысли на счет исключений: SYG>>Исключения бывают "вредные" — то есть те которые и быть-то не должны — они сигнализируют о сбое работы программы, если они возникают, значит программа написана криво; а бывают "полезные" — это те исключения, которых ожидают и обрабатывают согласно логике работы программы, они заранее были запланированы. Так вот в Component Pascal так сказать "вредные" исключения (выход индекса за пределы массива, неправильное приведение типа, не предусмотренный вариант выбора в инструкции CASE и т.п.) — просто автоматически немедленно останавливают работу программы и все — программиста на мыло!
E>Не, "автоматически немедленно" останавливать работу программы это полумера. Надо, чтобы она сама себя тут же и деинсталлировала и возвращала пользователю уплаченные за себя деньги, после чего "автоматически" коннектилась к сайту разработчиков и отправляла "на мыло" провинившегося программиста по имени "Component Pascal"
E> (шутка)
Кто-то сказал, что цитаты производят большее впечатление чем слова принадлежащие лично говорящему. Что же, процитирую Сергея Деревяго:
Стр.149: Задача 2.14. Исключения в конструкторах. Часть 2
M: Item 18. Constructor Failures, Part 2: Absorption?
А теперь маленькое философское отступление. Те, кто писал действительно серьезный код знают, что исключений, возбуждаемых при ошибках программиста (напр. std::logic_error, который определяется стандартом как: для извещения об ошибках, которые, предположительно, могут быть обнаружены до выполнения программы) быть не должно. Самое лучшее, что мы можем сделать при обнаружении подобного рода ошибки -- это сразу же прервать выполнение программы, сгенерировав информацию, необходимую для определения сути происшедшего (напр. core dump). Дело в том, что "ошибка здесь" является, как правило, следствием "ошибки там" и продолжение исполнения некорректного кода в надежде на лучшее приведет к Ужасным Последствиям (напр. сумма, эквивалентная нескольким десяткам лет зарплаты программиста, будет зачислена на неизвестный счет где-нибудь в Буркина-Фасо. Но это, конечно, маловероятно, т.к. чаще всего обнаруженное несоответствие двойной бухгалтерии приводит к временной остановке всех операций до выяснения причин; а убыток от нескольких часов простоя серьезного банка приводит к гораздо более дорогостоящим последствиям...).
Здравствуйте, AndreyFedotov, Вы писали:
AF> Мы тут чудненько пофлеймили на тему "о применимости С++ в серьёзном коде" , но как то за кадром остался вопрос о том, что же такое "серьёзный код". Были правда некоторые попытки определить это понятие, но они быстро иссякли. AF> А вы как думаете — какой код можно назвать "серъёзным" или "сложным"? Как Вы вообще — разделяете ли код по каким-либо критериям и на какие то категории? И если да, то по каким? AF> Некоторые уже упоминались. Например "лохокод" AF> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей. Какой нибудь навороченый алгоритм, с кучей условий (какая нибудь сложная сортировка или шифрование) — код сложный (алгоритмически), но тем не менее к серьёзному я его не отношу. По тем же причинам к серъёзному коду не отношу большинство модулей ОС, так как на мой взгляд — это код специфический — который должен быть написан крайне аккуратно и хорошо продуман, но чего-либо принципиально сложного в нем нет. AF> Наверняка у каждого из нас своя точка зрения по этому поводу. Предлагаю поделиться...
Мне кажеться, что "серъёзный" является синонимом "хорошего". Хороший код это адекватный код, в котором нет излишних наворотов и искуственнного усложнения. Обычно, такой код хорошо структуирован и полностью соответсвует принципу DRY(don't repeat yourself).
Re[14]: Внешнее не имеет непосредственной власти над внутрен
SYG>Теперь по пунктам. DG>> 1. Выделение памяти SYG>Выделение памяти для пользователей языка программирования является абсолютно безопасной операцией SYG>NEW(p); SYG>IF p # NIL THEN ... END; SYG>Если памяти недостаточно, то процедура NEW() всего лишь навсего вернет пустой (NIL) указатель. Никаких исключительных ситуаций при этом не возникнет.
Чуть философски отвлечемся.
Есть старое изречение "Счастливы все одиннаковы, несчастливы — каждый по своему".
Это изречение можно применить и к программам, в том смысле, что работа без ошибок всегда одиннакова — работа программы всегда выполняется идет по одной трасе, но каждая ошибка уникальна, т.к. сразу меняется трасса работы программы.
Если каждую ошибку обрабатывать отдельно, то сразу возникает проблема комбинаторного взрыва, т.к. на каждую трассу "хорошего" выполнения у нас может быть 10, 100, миллион трасс выполнения с обработкой ошибок.
Получается, что любыми способами надо упрощать обработку ошибок, иначе написать что-то действительно сложнее будет нереально в конечные сроки.
Для уменьшения этого комбинаторного взрыва применяется паттерн "транзакция" — если не выполнилась часть операции, то не выполняется вся операция с корректным откатом выполненных подопераций.
Для поддержки этого паттерна в языки были введены try/finally, деструкторы, исключения, using, декларируются такие под паттерны, как захват/освобождение ресурса должно оформляться в виде конструктор/деструктор.
Этот паттерн резко упрощает обработку ошибок, Т.к. теперь есть только один вид ошибки — нарушение нормального хода выполение программы. И уже не так важно, как именно этот ход нарушился.
Причем это нарушение может быть обработано на любом уровне, соответственно откатывая или не откатывая вышестоящие транзакции.
DG>> 2. Любые операции с внешним миром: операции с диском, сетью, интернетом, пользователем, другими программами и т.д. DG>> 3. Для случая распределенной программы, вообще, любой вызов функции может закончится неудачей, т.к. может быть именно в этот момент пропала связь с удаленным модулем.
SYG>Все эти операции абсолютно безопасны. Не читается дискета? — Великолепно, так и сообщим пользоваелю что не читается дискета, при чем здесь исключительная ситуация? Буфер порта TCP/IP протокола пустой — так и скажем пользователю что интернет упал. Где здесь исключение? Другая программа не отвечает — великолепно, не больно то и хотелось. Здесь нигде нет ни одной исключительной ситуации. Все ситуации — штатные, обычные, заранее известные.
Все это исключения, потому что все это нарушения "хорошего" выполнения программы, а значит все ошибки приводит к взрывному росту вариантов без увеличения функциональности..
1. Во-первых, как подоперация, которая обращается к дискете узнает, кто такой "пользователь"? И значит, как она ему выдаст ошибку? Может быть программа, вообще, работает в автоматическом режиме и никакого пользователя нет.
2. Во-вторых, кто будет все эти варианты разбирать и описывать? И сколько вариантов по Вашему надо обработать вариантов, у того простого действия, как запись файла на диск?
SYG>Вам не удалось привести ни одного примера потенциально опасной операции чей фатальный исход невозможно предугадать заранее путем проверки входных данных. Примеры, которые Вы привели, абсолютно безопасны просто в случае неудачи, например, возвращают FALSE вместо TRUE, но исключительных ситуаций они при этом не создают. Вы перепутали операции которые не могут быть выполнены — то есть завершаются фатально (например возвращая FALSE), с операциями которые во время выполнения приводят к возникновению исключительных ситуаций. К потенциально опасным операциям относятся: деление на ноль и другие арифметические переполнения, неправильный индекс массива, разыменование повисшего указателя, и, быть может, что-то еще. Но вот что?
Вы противоречите сами себе.
Что же опасного в делении на ноль? ЭТу операцию тоже можно заранее избежать:
if (y == 0)
return error;
else
z = x/y;
И с массивом ничего страшного не происходит
if (index < 0 || index >= array.length)
return error;
else
item = array[index];
даже с разименованием повисшего указателя нет ничего страшного:
if (!isAlive(pointer))
return error;
else
value = *pointer;
Можно сказать, что вы передергиваете.
Сначала говорите, что все в руках программы, и никаких исключительных ситуаций для программы нет, а потом вдруг приводите какие-то примеры, которые почему-то чуть более исключительные, чем все остальные.
Вот Вы в соседнем топике вспоминали про модули, про инкапсуляцию, про уменьшение комбинаторики.
Но почему в рамках этого обсуждения сразу об этом забываете.
А ведь в данном случае программа тоже состоит из модулей, и отдельным модулям как можно меньше хочется знать об ошибках друг друга, чтобы не увеличивать комбинаторное число вариантов.
Рассмотрим, например, модуль графический редактор. Модуль граф. редактор попросил модуль "хранилище" сохранить данные, и при этом модулю "граф. редактор" не важно, почему модуль "Хранилище" на смогло сохранить файл: память кончилась, дискету вытащили, прав не хватило, программист при написании модуля "хранилище" накосячил — для модуля "граф. редактор" — все эти ситуации исключительны, потому что граф. редактор хотел сохранить файл, а его обломали. И необходимо менять "нормальную" трассу выполнения программы.
SYG>А теперь маленькое философское отступление. Те, кто писал действительно серьезный код знают, что исключений, возбуждаемых при ошибках программиста (напр. std::logic_error, который определяется стандартом как: для извещения об ошибках, которые, предположительно, могут быть обнаружены до выполнения программы) быть не должно. Самое лучшее, что мы можем сделать при обнаружении подобного рода ошибки -- это сразу же прервать выполнение программы, сгенерировав информацию, необходимую для определения сути происшедшего (напр. core dump). Дело в том, что "ошибка здесь" является, как правило, следствием "ошибки там" и продолжение исполнения некорректного кода в надежде на лучшее приведет к Ужасным Последствиям (напр. сумма, эквивалентная нескольким десяткам лет зарплаты программиста, будет зачислена на неизвестный счет где-нибудь в Буркина-Фасо. Но это, конечно, маловероятно, т.к. чаще всего обнаруженное несоответствие двойной бухгалтерии приводит к временной остановке всех операций до выяснения причин; а убыток от нескольких часов простоя серьезного банка приводит к гораздо более дорогостоящим последствиям...).
Рассмотрим, например, программу управляющую аэропортом. В том числе эта программа рассчитывает насколько времени у самолета хватит топлива.
А теперь допустим, что на посадку вдруг решил зайти планер, у которого соответственно расход горючего ноль, программа попыталась рассчитать на сколько времени такому "самолету" хватит горючего, но произошла ошибка — деление ноль.
По Вашему получается, что в этом случае должен быть остановлена вся программа, при этом оставив висеть в воздухе все управляемые данной программой самолеты.
Т.е. получается, что Вы готовы на себя взять ответственность за жизнь всех людей, которые находились в воздухе?
Может все-таки стоило остановить только для данного самолета в данное время один единственный модуль, который рассчитывает расход горючего?
Вернемся к реальной жизни. В реальной жизни часто стоит задача построить надежную систему из ненадежных элементов, любые организации людей построены на этом принципе — т.е. любой человек может ошибаться, "ломаться", "выходить из строя", но организация в целом при этом продолжает стабильно работать.
Таже самая задача стоит и в программирование, в программировании тоже необходимо строить надежные системы из ненадежных элементов, из ненадежных модулей. В тяжелых случаях — отдельные модули, вообще, могут быть саботирующими — встроенными через хакерскую атаку.
Но выше перечисленный подход приводит к тому, что надежность всей системы не может быть выше, чем надежность самого ненадежного элемента, т.к. ненадежный элемент может в любой момент остановить работу всей системы.
ps
Можно даже сказать, что на совести людей, которые руководствуются логикой из цитаты, такие аварии как взрыв шатла во Франции, отказы марсианских программ. Именно в этих авариях небольшие ошибки в отдельных модулях привели к останову всей программы, и в конечном счете, к аварии.
Здравствуйте, DarkGray, Вы писали:
DG>Может все-таки стоило остановить только для данного самолета в данное время один единственный модуль, который рассчитывает расход горючего?
Что же Вы о создателях Оберон систем так плохо думаете? Разумеется будет остановлена работа только того модуля, который выполнил недопустимую операцию. Модуль будет динамически выгружен из системы. Когда другие модули запросят доступ к нему, он автоматически загрузится в память обратно. Так сказать — горячая перезагрузка — на лету. Вместо этого модуля, если угодно, может быть загружен модуль от другого производителя. Или, гипотетически, этот модуль будет "на лету" перекомпилирован заново, ошибка в нем исправлена, а его новый скомпилированный вариант динамически загружен в память. Что может быть устойчивее и надежнее? Вы бы, извините конечно, прежде чем глупые фантазии излагать вспомнили бы в каких областях Обероны используются: для случаев требующих особой безопасности — космос, электростанции, беспилотные летательные (военные) аппараты.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>А теперь маленькое философское отступление. Те, кто писал действительно серьезный код знают, что исключений, возбуждаемых при ошибках программиста (напр. std::logic_error, который определяется стандартом как: для извещения об ошибках, которые, предположительно, могут быть обнаружены до выполнения программы) быть не должно. Самое лучшее, что мы можем сделать при обнаружении подобного рода ошибки -- это сразу же прервать выполнение программы, сгенерировав информацию, необходимую для определения сути происшедшего (напр. core dump). Дело в том, что "ошибка здесь" является, как правило, следствием "ошибки там" и продолжение исполнения некорректного кода в надежде на лучшее приведет к Ужасным Последствиям (напр. сумма, эквивалентная нескольким десяткам лет зарплаты программиста, будет зачислена на неизвестный счет где-нибудь в Буркина-Фасо. Но это, конечно, маловероятно, т.к. чаще всего обнаруженное несоответствие двойной бухгалтерии приводит к временной остановке всех операций до выяснения причин; а убыток от нескольких часов простоя серьезного банка приводит к гораздо более дорогостоящим последствиям...).
1. Core dump во многих случаях мало полезен (или вообще бесполезен).
Часто нужно более информативное, краткое и точное описание проблемы.
Вот некоторые (очевидные) аргументы: — его неудобно читать (по сравнение с текстовым описание ошибки) и/или траспортировать (файл в 512мб по почте в службу поддержки уже не пошлешь)- если речь идет о распределенной системе (пусть даже простой клиент-серверной), то полный дамп не всегда и сформировать-то получится. Программы ведь на разных машинах живут.- не стоит пугать пользователей бессмысленными сообщениями типа "Внутренняя ошибка приложения. Подробнее смотрите дамп памяти (512мб нулей и единиц), а лучше обратитесь в службу поддержки. В дельнейшем не рекомендуем Вам выполнять тот набор действий, который привел к ошибке (вы ведь наверняка должны точно помнить две сотни кнопок, которые нажали за последние три часа?)
Кстати, а хотя бы core dump твой ComponentPascal делать умеет?
2. Не всякие программы оперируют "суммами эквивалентными нескольким десяткам годовых зарплат программиста" . Говорят, что бываю такие, которые вообще никак с деньгами не связаны
3. Во многих случаях, при "экстренном завершении" программы необходимо, чтобы она всё же успела выполнить некоторый финализующий код (в идеале — отработали деструкторы всех объектов), например: - на экране появился хоть какой-нибудь диалог, сообщающий (на русском языке, с отсылкой к службе поддержки и ссылками на пункты хелпа)- было возможность немедленно отправить разработчикам по почте багрепорт- если это был текстовый редактор, то нужно предложить пользователю сохранить текст, который он набирал в последние несколько часов.- были закрыты все файлы/коннекты-к-бд/сессии-работы-со-внешними-устройствами (например приводами чтения кредитных карт)
Кстати, если не выполнить действия из предыдущего пункта, то при следующем запуске как раз таки и может случиться та самая ошибка, приводящая к "убыткам от нескольких часов простоя серьезного банка"
4. Напоминаю, что есть такая технология, называется "plug in".
Я так понимаю, ты предлагаешь разработчику основного приложения смириться с тем, что оно может быть в любой момент закрыто, если в одном из плагинов (даже не им написанных) произошла ошибка?
Как по мне, так лучше просто отключить проблемный плагин.
... << RSDN@Home 1.1.3 stable >>
Re[15]: Недопустимая операция = Исключительная ситуация
Вы просто напросто используете термин "исключительная ситуация" для все чего ни попадя:
DG>для модуля "граф. редактор" — все эти ситуации исключительны, потому что граф. редактор хотел сохранить файл, а его обломали.
Тем не менее, ни в одном из приведенных Вами примеров не было по настоящему "исключительной ситуации", то есть такой когда программа выполняет некоторое действие другими словами называемое "недопустимая операция". Нельзя вычислить квадратный корень из отрицательного числа, нельзя разделить на ноль, нельзя работать с чужой памятью, но при этом, сколько угодно раз можно отказать в сохранении или открытии файла — это не является "недопустимой операцией". Разницу понимаете?
P.S.
К делу вообще-то не относится, но, видимо Вы еще и слово "модуль" используете для всего чего ни попадя. Нет такого модуля "граф. редактор". Программа "граф. редактор" — состоит из нескольких десятков модулей (а может и сотен). Модуль — это довольно мелкая единица, она меньше чем программа, но больше чем класс.
Программа >> Модуль >> Класс
Если Вы программируете на С++, то первым грубым приближением к понятию модуль будет просто один файл с исходным кодом, но этот файл компилируется в одну DLL-ку. Вот сколько файлов Вам понадобилось для написания программы "граф. редактор" — вот из стольки модулей она и состоит, причем каждый из них динамически загружается/выгружается во время работы программы. Язык С++ разумеется этого не поддерживает (так чтоб автоматом каждый файл в отдельную DLL-ку компилить), но в общем и целом модулем называется именно это.
Здравствуйте, eugals, Вы писали:
E>Кстати, а хотя бы core dump твой ComponentPascal делать умеет?
Во-первых, Component Pascal — это язык и сам по себе он ничего делать не умеет. На нем писать самому надо. Во-вторых, скачайте из интернета доки и узнайте. Я почему-то о С++ подобных вопросов не задаю, типа "А ваш С++, ваще, хотя бы умеет делать то-то или то-то?"
E>4. Напоминаю, что есть такая технология, называется "plug in". E>Я так понимаю, ты предлагаешь разработчику основного приложения смириться с тем, что оно может быть в любой момент закрыто, если в одном из плагинов (даже не им написанных) произошла ошибка? E>Как по мне, так лучше просто отключить проблемный плагин.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Ну это быстренько можно "подпортить", и "рульность" С++ поубавится SYG>1) Пусть a,b,c — это очень большие объекты, так что на стеке втроем им места не хватит... SYG>2) Пусть a,b,c — это не объекты, а полиморфные переменные. В терминологии С++ статический тип a,b,c — пусть будет указатели на объекты "абстрактных классов". Так как в стандартном С++ есть только блок try catch, а FINALLY — нету, то жизнь сразу усложняется. Придется использовать классы обертки — "умные указатели", а это уже из другой оперы.
Ответ на оба вопроса — Master Pointers ("ведушие указатели", Джеф Элджер, например). Нет никакой "другой оперы".
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Во-первых, Component Pascal — это язык и сам по себе он ничего делать не умеет. На нем писать самому надо. Во-вторых, скачайте из интернета доки и узнайте.
Запустил сейчас на RSDN поиск строки "Compоnent Pascal" — 13 ccылок. Из них наверное половина твоих.
Пожалуй я, с твое разрешения, прощу себе, что до сегодняшнего дня про него кроме названия ничего не слышал
Что же касается твоего предложения "скачать доки", то я от этого на данный момент воздержусь — пока что твои рекламные сообщение не убеждают, что оно будет стоит потраченного времени. А судя по твоей реакции на мои попытки узнать о CP что-нибудь вразумительное, врял ли когда-нибудь это положение изменится
SYG> Я почему-то о С++ подобных вопросов не задаю, типа "А ваш С++, ваще, хотя бы умеет делать то-то или то-то?"
А ты задай — ответят
(кстити, набери в поиске RSDN "С++" и посчитай сколько ссылок будет там)
SYG>Уже ответил: SYG>http://www.rsdn.ru/Forum/Message.aspx?mid=725690&only=1
SYG>Вы просто напросто используете термин "исключительная ситуация" для все чего ни попадя:
DG>>для модуля "граф. редактор" — все эти ситуации исключительны, потому что граф. редактор хотел сохранить файл, а его обломали.
SYG>Тем не менее, ни в одном из приведенных Вами примеров не было по настоящему "исключительной ситуации", то есть такой когда программа выполняет некоторое действие другими словами называемое "недопустимая операция". Нельзя вычислить квадратный корень из отрицательного числа, нельзя разделить на ноль, нельзя работать с чужой памятью, но при этом, сколько угодно раз можно отказать в сохранении или открытии файла — это не является "недопустимой операцией". Разницу понимаете?
Нет, не понимаю.
Я не вижу разницу между операциями "Деление на ноль", "Взять неберущийся интеграл", "Открыть файл, которого нет на диске", "Открыть файл, который не доступен".
Во всех этих случаях, можно сказать, что есть некий логический просчет, который и привел к возникновению данной ситуации.
И мне не понятно, почему какие-то из этих случаев объявляются более исключительными, чем другие, другими словами я не вижу критерия по которому производится это деление.
SYG>P.S. SYG>К делу вообще-то не относится, но, видимо Вы еще и слово "модуль" используете для всего чего ни попадя. Нет такого модуля "граф. редактор". Программа "граф. редактор" — состоит из нескольких десятков модулей (а может и сотен). Модуль — это довольно мелкая единица, она меньше чем программа, но больше чем класс.
Вопрос на засыпку:
если мы несколько модулей объединили вместе, то какой "элемент" мы получили в итоге? сразу программу?
SYG>Программа >> Модуль >> Класс
Чуть продолжу Вашу мысль, получается, что если мы граф. редактор используем, как подчасть более большой программы, то граф. редактор автоматом становится модулем, потому что с одной стороны — это не класс, но с другой стороны — это и не программа, т.к. редактор получился встроенным в другую программу.
ps
но если чуть пофилософствовать, то понятие модуль в себя включает и такие понятия, как программа, класс, package, unit, объект и т.д. Все зависит только от того, на каком уровне абстракции мы находимся, и какой язык программирования используем.
SYG>Если Вы программируете на С++, то первым грубым приближением к понятию модуль будет просто один файл с исходным кодом, но этот файл компилируется в одну DLL-ку. Вот сколько файлов Вам понадобилось для написания программы "граф. редактор" — вот из стольки модулей она и состоит, причем каждый из них динамически загружается/выгружается во время работы программы. Язык С++ разумеется этого не поддерживает (так чтоб автоматом каждый файл в отдельную DLL-ку компилить), но в общем и целом модулем называется именно это.
Возьмем, например, Word.
Встроенный в Word граф. редактор диаграмм — на Ваш взгляд — это модуль, программа или класс?
ps
Мы с Вами очень подробно подискутировали о терминах, но по существу какие-то возражения будут?
Или в целом, Вы согласны с моими доводами?
DG>>Может все-таки стоило остановить только для данного самолета в данное время один единственный модуль, который рассчитывает расход горючего?
SYG>Что же Вы о создателях Оберон систем так плохо думаете?
Я думаю плохо не об Обероне, а о Вашей позиции "в случае ошибки необходимо останавливать всю программу".
SYG> Разумеется будет остановлена работа только того модуля, который выполнил недопустимую операцию. Модуль будет динамически выгружен из системы. Когда другие модули запросят доступ к нему, он автоматически загрузится в память обратно. Так сказать — горячая перезагрузка — на лету. Вместо этого модуля, если угодно, может быть загружен модуль от другого производителя. Или, гипотетически, этот модуль будет "на лету" перекомпилирован заново, ошибка в нем исправлена, а его новый скомпилированный вариант динамически загружен в память.
На словах все отлично.
Но непонятно, что в этом случае будет с модулями, которые использовали/вызывали данные модули? Они тоже будут выгружены? Или они получать сообщение об ошибке? Другими словами получат исключение?
Что будет с ресурсами, модулями и т.д., которые использовал выгружаемый модуль?
Что будет с ходом выполнения программы? Выполнение остановится? продолжится с какого-то места? еще что-то?
SYG>Ну как, можно считать вопрос на этом исчерпанным?
пока есть только лозунг "оберон — это круто, а, ну, все быстро пользуйтесь обероном", но нет ни одного конкретного описания или примера, как в обероне решаются затронутые в данной теме проблемы.
Здравствуйте, Sir Wiz, Вы писали:
SW>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>Ну это быстренько можно "подпортить", и "рульность" С++ поубавится SYG>>1) Пусть a,b,c — это очень большие объекты, так что на стеке втроем им места не хватит... SYG>>2) Пусть a,b,c — это не объекты, а полиморфные переменные. В терминологии С++ статический тип a,b,c — пусть будет указатели на объекты "абстрактных классов". Так как в стандартном С++ есть только блок try catch, а FINALLY — нету, то жизнь сразу усложняется. Придется использовать классы обертки — "умные указатели", а это уже из другой оперы. SW>Ответ на оба вопроса — Master Pointers ("ведушие указатели", Джеф Элджер, например). Нет никакой "другой оперы".
Это как раз и есть та самая "другая опера". "Другая опера" связа с тем как в С++ появляются эти самые умные, ведущие и прочие указатели. Они возможны в силу того что в С++ есть шаблоны. То что шаблоны — это точно "другая опера" Вы согласны? В свою очередь, шаблоны столь эффективны благодаря тому, что есть перегрузка операторов. То что перегрузка операторов — это точно "другая опера" Вы согласны? Вы вот, сможете без шаблонов и перегруженных операторов создать реализацию обертки указателя? Ответ — нет, не сможете. Для того чтобы всего лишь навсего эмулировать действие FINALLY Вам понадобится использовать грандиознейший по своему размаху механизм под названием "шаблоны"+"перегрузка операторов"+"автоматический вызов деструкторов для стековых объектов". Безусловно это уже другая опера. А вот в Delphi для этого просто ввели одно дополнительное словечко — FINALLY и проблемы не стало.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SW>>Ответ на оба вопроса — Master Pointers ("ведушие указатели", Джеф Элджер, например). Нет никакой "другой оперы".
SYG>Это как раз и есть та самая "другая опера". "Другая опера" связа с тем как в С++ появляются эти самые умные, ведущие и прочие указатели. Они возможны в силу того что в С++ есть шаблоны. То что шаблоны — это точно "другая опера" Вы согласны? В свою очередь, шаблоны столь эффективны благодаря тому, что есть перегрузка операторов. То что перегрузка операторов — это точно "другая опера" Вы согласны? Вы вот, сможете без шаблонов и перегруженных операторов создать реализацию обертки указателя? Ответ — нет, не сможете.
Право, я вас уверяю, это не "другая опера", это язык С++. Это штатные средства языка С++. Что в этом плохого, как вы считаете?
SYG>Для того чтобы всего лишь навсего эмулировать действие FINALLY Вам понадобится использовать грандиознейший по своему размаху механизм под названием "шаблоны"+"перегрузка операторов"+"автоматический вызов деструкторов для стековых объектов". Безусловно это уже другая опера. А вот в Delphi для этого просто ввели одно дополнительное словечко — FINALLY и проблемы не стало.
О, ничего грандиозного, всё очень просто. И не для эмуляции действия FINALLY это делается. Сама мысль о эмуляции того-чего-не-нужно в С++ странна. Master Pointers это идиома и уповать на то, что такие идиомы не встроены в язык странно. Поскольку С++ в некотором роде является языком для описания идиом и писания идиомами. В этом гибкость и красота. Я могу воспользоваться другой идиомой. А Delphi — ссылки на объекты и только.
Здравствуйте, DarkGray, Вы писали:
DG>Я думаю плохо не об Обероне, а о Вашей позиции "в случае ошибки необходимо останавливать всю программу".
Мы просто под словом "ошибка" понимали разные вещи. Я под "ошибкой" понимал "недопустимую операцию", а Вы под "ошибкой" понимали все что угодно вплоть до отказа загрузки/сохранения файла. Кроме того я, по недосмотру, допустил вольность употребив слово Программа имея ввиду выполняемый модуль, а Вы не зная специфики работы многомодульных программ предположили что я собираюсь остановить работу всей ОС.
DG>Но непонятно, что в этом случае будет с модулями, которые использовали/вызывали данные модули? Они тоже будут выгружены? Или они получать сообщение об ошибке? Другими словами получат исключение? DG>Что будет с ресурсами, модулями и т.д., которые использовал выгружаемый модуль? DG>Что будет с ходом выполнения программы? Выполнение остановится? продолжится с какого-то места? еще что-то?
Точно не отвечу. Система BlackBox (эмулятор ОС Оберон под Виндос), кажется, переходит к выполнению следующей итерации своего главного цикла. Если есть исходный код модуля, то выскакиевает диалоговое окно со списком стека вызовов последних нескольких процедур со всеми значениями локальных переменных. Каждый элемент этого списка является гиперссылкой на соответсвующую позицию в исходном коде программы. С ресурсами ничего страшного не происходит — всем управляет единый сборщик мусора. Как конкретно обстоят дела в нативной ОС Оберон и ее многочисленных клонах я не знаю. Кроме того, есть еще парралельные системы, например, Blue Bottle на Active Oberon — там парралельность интегрирована в сам язык. Как там все внутрях устроено я еще тоже не знаю.
SYG>>Ну как, можно считать вопрос на этом исчерпанным? DG>пока есть только лозунг "оберон — это круто, а, ну, все быстро пользуйтесь обероном", но нет ни одного конкретного описания или примера, как в обероне решаются затронутые в данной теме проблемы.
Какие проблемы-то? Я позволил себе сказать, что в Оберонах нет механизма "исключительных ситуаций" и объяснил почему он там излишен. Если Вы видите проблему, то объясните в чем состоит ее суть?
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Что же Вы о создателях Оберон систем так плохо думаете? Разумеется будет остановлена работа только того модуля, который выполнил недопустимую операцию. Модуль будет динамически выгружен из системы. Когда другие модули запросят доступ к нему, он автоматически загрузится в память обратно. Так сказать — горячая перезагрузка — на лету. Вместо этого модуля, если угодно, может быть загружен модуль от другого производителя. Или, гипотетически, этот модуль будет "на лету" перекомпилирован заново, ошибка в нем исправлена, а его новый скомпилированный вариант динамически загружен в память. Что может быть устойчивее и надежнее? Вы бы, извините конечно, прежде чем глупые фантазии излагать вспомнили бы в каких областях Обероны используются: для случаев требующих особой безопасности — космос, электростанции, беспилотные летательные (военные) аппараты.
А почему нужно выгружать именно модуль (в том значении этого слова, в котором ты его понимаешь)? Почему не группу модулей? Или наоборот — один только класс из "модуля"? Или Метод? Или, даже, секцию кода внутри метода (расположенную в блоке try)?
И (DarkGray про это уже рядом сказал), как мне описать процедуру выгрузки (в смысле разрешения конфликтов с другими модулями), чтобы указать что вот этот вот модуль нужно перечитать, а вот эти не трогать, а вместо этого, в случае чего, можно взять вон тот и т.п.? Для этого нужно какой-то параллельный код держать (в котором, кстати, в свою очередь, тоже возможны ошибки) и постоянно следить за его релевантностью.
И вообще, почему обязательно "выгружать"? Может программисту в данных обстоятельствах проще только прервать выполнение проблемной секции, для чего (в частности) собственно и существуют эти самые исключения...
... << RSDN@Home 1.1.3 stable >>
Re[17]: Недопустимая операция = Исключительная ситуация
Здравствуйте, DarkGray, Вы писали:
SYG>>Тем не менее, ни в одном из приведенных Вами примеров не было по настоящему "исключительной ситуации", то есть такой когда программа выполняет некоторое действие другими словами называемое "недопустимая операция". Нельзя вычислить квадратный корень из отрицательного числа, нельзя разделить на ноль, нельзя работать с чужой памятью, но при этом, сколько угодно раз можно отказать в сохранении или открытии файла — это не является "недопустимой операцией". Разницу понимаете?
DG>Нет, не понимаю. DG>Я не вижу разницу между операциями "Деление на ноль", "Взять неберущийся интеграл", "Открыть файл, которого нет на диске", "Открыть файл, который не доступен".
Файлы бывают не доступными, а еще файлы могут вообще отсутствовать на диске. Вы это знаете и программа Ваша тоже должна это знать. И для нее не должно быть сюрпризом то что файла нету. Это обычная штатная ситуация. Иногда файлы на диске есть, а иногда их нет. Иногда их можно прочитать/записать, а иногда бывает нельзя. Все это совершенно обычно. А вот разделить на ноль нельзя никогда, даже после дождичка в четверг и то нельзя разделить на ноль, даже если долго упрашивать компьтер и танцевать с бубном, все равно нельзя — это недопустимая операция была есть и будет вечно. По чужому адресу нельзя писать и читать ни сегодня ни завтра ни через сто лет — это недопустимая операция. Нелья вычислить значение квадратного корня из отрицательного числа ни сегодня ни завтра ни через сто лет — это недопустимая операция. Такую разницу понимаете?
DG>Вопрос на засыпку: DG>если мы несколько модулей объединили вместе, то какой "элемент" мы получили в итоге? сразу программу?
А если мы сделаем DLL-ку размером 1 гигабайт, то это все равно будет DLL-ка или это уже будет что-то другое? Утрированное понятие модуля — это самая обычная DLL-ка, динамически загружаемая единица исполнения.
DG>Возьмем, например, Word. DG>Встроенный в Word граф. редактор диаграмм — на Ваш взгляд — это модуль, программа или класс?
Word — это приложение работающее под OS Windows. Виндос не является модульной ОС и не обладает единым сборщиком мусора. Под Виндос нельзя писать полноценные многомодульные программы. Виндозные DLL-ки не обслуживаются никаким единым Виндозным сборщиком мусора. Я упоминал про BlackBox — это эмуляция ОС Оберон под Виндос. Микрософт сейчас ляпает платформу .NET — для того чтобы можно было писать многомодульные программы.
DG>Мы с Вами очень подробно подискутировали о терминах, но по существу какие-то возражения будут? DG>Или в целом, Вы согласны с моими доводами?
Доводами о чем?
Здравствуйте, Sir Wiz, Вы писали:
SW>О, ничего грандиозного, всё очень просто. И не для эмуляции действия FINALLY это делается. Сама мысль о эмуляции того-чего-не-нужно в С++ странна. Master Pointers это идиома и уповать на то, что такие идиомы не встроены в язык странно. Поскольку С++ в некотором роде является языком для описания идиом и писания идиомами. В этом гибкость и красота. Я могу воспользоваться другой идиомой. А Delphi — ссылки на объекты и только.
Ну и чего вот Вы этим самым сказали? Кто Вас за язык-то тянул? Вы самолично только что расписались в том, что используя язык С++ для решения какой-либо (быть может очень сложной) задачи предметной области, Вы обрекаете самого себя еще и на решение (быть может не менее сложных) задач присущих самому языку С++ без относительно к задаче предметной области. То есть вынуждены будете напрягаться больше чем необходимо. И все это в топике "Серьезный код", в котором уже не раз подразумевалось, что серьезный код должен быть на столько простым на сколько это вообще возможно.
Re[18]: Недопустимая операция = Исключительная ситуация
SYG>Файлы бывают не доступными, а еще файлы могут вообще отсутствовать на диске. Вы это знаете и программа Ваша тоже должна это знать. И для нее не должно быть сюрпризом то что файла нету. Это обычная штатная ситуация. Иногда файлы на диске есть, а иногда их нет. Иногда их можно прочитать/записать, а иногда бывает нельзя. Все это совершенно обычно. А вот разделить на ноль нельзя никогда, даже после дождичка в четверг и то нельзя разделить на ноль, даже если долго упрашивать компьтер и танцевать с бубном, все равно нельзя — это недопустимая операция была есть и будет вечно. По чужому адресу нельзя писать и читать ни сегодня ни завтра ни через сто лет — это недопустимая операция. Нелья вычислить значение квадратного корня из отрицательного числа ни сегодня ни завтра ни через сто лет — это недопустимая операция. Такую разницу понимаете?
не понимаю, Вы опять передергиваете.
Потому что операцию деления на ноль — вы воспринимаете, как деление на константу 0, а не как деление на переменную, которая иногда принимает в том числе и значение 0.
В этом случае, мы получаем все тоже самое, что и с файлами: что иногда мы делить на данную переменную можем, а иногда не можем.
Даже повторю Ваши слова "и для программы не должно быть сюрпризом, что иногда на данную переменную делить нельзя, а иногда можно."
Могу даже довести ситуацию с файлами к ситуации с делением на ноль.
Например, файл с именем ":" создать никогда нельзя, даже после дождика в четверг, но по Вашему получается, что это все равно не исключительная ситуация.
DG>>Вопрос на засыпку: DG>>если мы несколько модулей объединили вместе, то какой "элемент" мы получили в итоге? сразу программу?
SYG>А если мы сделаем DLL-ку размером 1 гигабайт, то это все равно будет DLL-ка или это уже будет что-то другое? Утрированное понятие модуля — это самая обычная DLL-ка, динамически загружаемая единица исполнения.
Фиг с ними с Dll-ками, Вы так и не ответили, что такое модуль?
DG>>Возьмем, например, Word. DG>>Встроенный в Word граф. редактор диаграмм — на Ваш взгляд — это модуль, программа или класс? SYG>Word — это приложение работающее под OS Windows. Виндос не является модульной ОС и не обладает единым сборщиком мусора. Под Виндос нельзя писать полноценные многомодульные программы. Виндозные DLL-ки не обслуживаются никаким единым Виндозным сборщиком мусора. Я упоминал про BlackBox — это эмуляция ОС Оберон под Виндос. Микрософт сейчас ляпает платформу .NET — для того чтобы можно было писать многомодульные программы.
хм, т.е. я, правильно, понял что "истинные модули" есть только в обероне, а во всех остальных языках — это так, одно название?
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Все это совершенно обычно. А вот разделить на ноль нельзя никогда, даже после дождичка в четверг и то нельзя разделить на ноль, даже если долго упрашивать компьтер и танцевать с бубном, все равно нельзя — это недопустимая операция была есть и будет вечно.
Вот пример:
oo — это "+бесконечность", очень удобная константа. я её использовал в качстве границы для свой функции вычиления пределов.
Очень лаконичный и прозрачный код при этом получался
SYG> По чужому адресу нельзя писать и читать ни сегодня ни завтра ни через сто лет — это недопустимая операция.
В досе можно. Кстати, что считать "чужим" адресом. Для ОС и её расширений вся память — своя. И во всяком случае, попытка записи в чужой адрес ещё не повод останавливать процесс. всякое бывает...
SYG> Нелья вычислить значение квадратного корня из отрицательного числа ни сегодня ни завтра ни через сто лет — это недопустимая операция.
Хм, уж вам, как кандидату физико-математических наук, говорить это должно быть стыдно А мнимые числа?
SYG>А если мы сделаем DLL-ку размером 1 гигабайт, то это все равно будет DLL-ка или это уже будет что-то другое? Утрированное понятие модуля — это самая обычная DLL-ка, динамически загружаемая единица исполнения. SYG>Word — это приложение работающее под OS Windows. Виндос не является модульной ОС и не обладает единым сборщиком мусора. Под Виндос нельзя писать полноценные многомодульные программы. Виндозные DLL-ки не обслуживаются никаким единым Виндозным сборщиком мусора. Я упоминал про BlackBox — это эмуляция ОС Оберон под Виндос. Микрософт сейчас ляпает платформу .NET — для того чтобы можно было писать многомодульные программы.
Ну правильно, сначала за уши притягиваем аналогию между модулями Оберона и DLL-ками виндов, а потом мастерски доказываем, что виндовые модули, по сравнению с обероновскими ни на что не годятся
... << RSDN@Home 1.1.3 stable >>
Re[19]: Недопустимая операция = Исключительная ситуация
Здравствуйте, DarkGray, Вы писали:
DG>Даже повторю Ваши слова "и для программы не должно быть сюрпризом, что иногда на данную переменную делить нельзя, а иногда можно." DG>Могу даже довести ситуацию с файлами к ситуации с делением на ноль. DG>Например, файл с именем ":" создать никогда нельзя, даже после дождика в четверг, но по Вашему получается, что это все равно не исключительная ситуация.
Мне что теперь, каждую свою фразу окружать сонмищем оговорок, в которых описывать все варианты ее истинности и толкования? Разумеется мы делим на переменную, и чтобы не совершить недопустимую операцию нам надо сначала проверять ее на неравенство нулю. А перед тем как создавать файл надо разумеется проверить его имя на допустимость. Но разница между этими двумя случаями состоит в том, даже не знаю как и объяснить-то, компьютер так что ли устроен, что делить на ноль он не может ну никак, а вот файл с недопустимым именем создает не компьютер, а программа, и она увидев недопустимое имя, просто не будет создавать такой файл и все, ничего страшного и исключительного не произойдет. Я не знаю как еще объяснить. Мне для этого компьютерной грамотности не хватает.
DG>Фиг с ними с Dll-ками, Вы так и не ответили, что такое модуль? DG>хм, т.е. я, правильно, понял что "истинные модули" есть только в обероне, а во всех остальных языках — это так, одно название?
Да, Вы правильно поняли. Вот например Дельфийский UNIT — это не модуль. Он хоть и является единицей инкапсуляции и компиляции, но вот динамически загружаемой/выгружаемой единицей исполнения не является.
Попробую собрать в одном месте все что я говорил о модулях.
Модуль — это:
во-первых, абстракция языка программирования являющаяся единицей инкапсуляции и компиляции (весь исходный код программы находится в модулях)
во-вторых, являющаяся единицей исполнения. Во время выполнения программы модули динамически загружаются/выгружаются (позднее связывание).
в-третьих, на саму систему (в которой эти модули работают) налагается ограничение — обязательно должен быть единый сборщик мусора (это для того чтобы модули могли безбоязненно создавать внутри себя объекты и передавать их другим модулям, а те третьим и т.д.).
Система построенная по такому принципу очень легко расширяется, модифицируется и т.д. Ведь каждый модуль можно в любой момент времени заменить на аналогичный модуль, но от другого производителя.
Re[20]: Недопустимая операция = Исключительная ситуация
SYG>Мне что теперь, каждую свою фразу окружать сонмищем оговорок, в которых описывать все варианты ее истинности и толкования? Разумеется мы делим на переменную, и чтобы не совершить недопустимую операцию нам надо сначала проверять ее на неравенство нулю. А перед тем как создавать файл надо разумеется проверить его имя на допустимость. Но разница между этими двумя случаями состоит в том, даже не знаю как и объяснить-то, компьютер так что ли устроен, что делить на ноль он не может ну никак, а вот файл с недопустимым именем создает не компьютер, а программа, и она увидев недопустимое имя, просто не будет создавать такой файл и все, ничего страшного и исключительного не произойдет. Я не знаю как еще объяснить. Мне для этого компьютерной грамотности не хватает.
С вашим подходом код будет примерно следующий:
Нам надо открыть файл, это вовлекает вызов цепочки функций.
SYG>Вот уж кто в таких случаях на самом деле по взрослому рулит, так это (компилируемый) язык со сборщиком мусора и без "исключительных ситуаций", например, Component Pascal (http://www.inr.ac.ru/~info21/cpascal/cp_report_1.4_rus.htm)
Какие серьезные продукты созданы на базе этого языка ?
Душа обязана трудиться! (с) Н.Заболоцкий.
Re[18]: Недопустимая операция = Исключительная ситуация
S.Yu.Gubanov -> "Re[17]: Недопустимая операция = Исключительная ситуация" :
SG> это совершенно обычно. А вот разделить на ноль нельзя SG> никогда, даже после дождичка в четверг и то нельзя разделить SG> на ноль, даже если долго упрашивать компьтер и танцевать с бубном, SG> все равно нельзя — это недопустимая операция была есть и будет
Хм... остатки знаний из инсттиута подсказывают, что при делении на ноль у
нас получится бесконечность и некоторые языки это поддерживают. Правда будет
ли в этом конкретный практический смысл — не ясно
SG> вечно. По чужому адресу нельзя писать и читать ни сегодня ни завтра SG> ни через сто лет — это недопустимая операция. Нелья вычислить
Ну вот, а как же данные шарить между процессами?
SG> значение квадратного корня из отрицательного числа ни сегодня ни SG> завтра ни через сто лет — это недопустимая операция. Такую SG> разницу понимаете?
Ну да. Математики — враги народа — напридумывали всяких комплексных числел
Вон, DSP шники мучаются с преобразованиями Фурье
SYG> Но разница между этими двумя случаями состоит в том, даже не знаю как и объяснить-то, компьютер так что ли устроен, что делить на ноль он не может ну никак, а вот файл с недопустимым именем создает не компьютер, а программа, и она увидев недопустимое имя, просто не будет создавать такой файл и все, ничего страшного и исключительного не произойдет. Я не знаю как еще объяснить. Мне для этого компьютерной грамотности не хватает.
Дык, процессор — это такая же программа, но только выполненная в железе. Она также может увидеть недопустимый делитель, и ничего не делать.
Вот только непонятно, что это такое "ничего не делать" и в том, и вдругом случае?
т.е. что все-таки должен сделать код, который вдруг увидел недопустимое имя файла?
SYG>Попробую собрать в одном месте все что я говорил о модулях.
SYG>Модуль — это: SYG>во-первых, абстракция языка программирования являющаяся единицей инкапсуляции и компиляции (весь исходный код программы находится в модулях) SYG>во-вторых, являющаяся единицей исполнения. Во время выполнения программы модули динамически загружаются/выгружаются (позднее связывание). SYG>в-третьих, на саму систему (в которой эти модули работают) налагается ограничение — обязательно должен быть единый сборщик мусора (это для того чтобы модули могли безбоязненно создавать внутри себя объекты и передавать их другим модулям, а те третьим и т.д.).
SYG>Система построенная по такому принципу очень легко расширяется, модифицируется и т.д. Ведь каждый модуль можно в любой момент времени заменить на аналогичный модуль, но от другого производителя.
Под такое определение подходят, например, Java, .Net, SmallTalk, почти все скриптовые языки, системы построеные на основе COM/DCOM и т.д.
Здравствуйте, _Obelisk_, Вы писали:
_O_>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>Вот уж кто в таких случаях на самом деле по взрослому рулит, так это (компилируемый) язык со сборщиком мусора и без "исключительных ситуаций", например, Component Pascal (http://www.inr.ac.ru/~info21/cpascal/cp_report_1.4_rus.htm)
_O_>Какие серьезные продукты созданы на базе этого языка ?
Здравствуйте, DarkGray, Вы писали:
DG>т.е. что все-таки должен сделать код, который вдруг увидел недопустимое имя файла?
Это философский вопрос или как?
Отсечка неправильных данных должна произойти на входе данных в систему. То есть, пользователь ввел неправильные данные, а они раз, и не ввелись, а выскочило диалоговое окно — "Введенные данные не правильные." Внутри системы неправильных данных быть не должно.
SYG>Точно не отвечу. Система BlackBox (эмулятор ОС Оберон под Виндос), кажется, переходит к выполнению следующей итерации своего главного цикла. Если есть исходный код модуля, то выскакиевает диалоговое окно со списком стека вызовов последних нескольких процедур со всеми значениями локальных переменных. Каждый элемент этого списка является гиперссылкой на соответсвующую позицию в исходном коде программы. С ресурсами ничего страшного не происходит — всем управляет единый сборщик мусора. Как конкретно обстоят дела в нативной ОС Оберон и ее многочисленных клонах я не знаю. Кроме того, есть еще парралельные системы, например, Blue Bottle на Active Oberon — там парралельность интегрирована в сам язык. Как там все внутрях устроено я еще тоже не знаю.
Но здесь опять же возникает вопрос, а как система узнает о том, что произошла ошибка? Получает некий сигнал? Чем этот сигнал отличается от исключения из "стандартных" языков программирования?
Здравствуйте, DarkGray, Вы писали:
DG>Но здесь опять же возникает вопрос, а как система узнает о том, что произошла ошибка? Получает некий сигнал? Чем этот сигнал отличается от исключения из "стандартных" языков программирования?
Может и ни чем.
Просто программисту запрещено возбуждать свои собственные псевдоисключительные ситуации.
Re[22]: Недопустимая операция = Исключительная ситуация
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.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Ну и чего вот Вы этим самым сказали? Кто Вас за язык-то тянул? Вы самолично только что расписались в том, что используя язык С++ для решения какой-либо (быть может очень сложной) задачи предметной области, Вы обрекаете самого себя еще и на решение (быть может не менее сложных) задач присущих самому языку С++ без относительно к задаче предметной области.
Хм!? Разве масте-поинтеры это сложно? Я один раз потратил пол часа на реализацию мастер-поинтеров и теперь спокойно их использую. SYG>То есть вынуждены будете напрягаться больше чем необходимо. И все это в топике "Серьезный код", в котором уже не раз подразумевалось, что серьезный код должен быть на столько простым на сколько это вообще возможно.
Вот именно. В базовой реализации просто не возможно предусмотреть все что может понадобится и код получится больше и сложнее.
Я пару раз расширял интерфейс своих мастер-поинтеров для того чтобы упростить их использование. Короче написав десяток строк я съекономил десятки тысячь строк.
Слабо сделать такое с тем что реализовано в языке?
Я на счет finally это не в C++ при помощи автоматических деструкторов эмулируют finally, а в других языках при помощи finally эмулируют автоматические деструкторы.
Надеюсь не надо обьяснять почему код написаный однажды лучше кода написаного тысячи раз.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Вот и слава богу, что для такого способа решения задач он не предназначен!
Таких задачь огромное колличество. Вот я писал OPC серверы. Я бы повесился если бы в С++ небыло исключений.
SYG>Думаю, что ПО для электростанции под эту категорию подходит в самый раз.
А я писал софт для нефтяных заводов. Там надежность тоже должна быть мягко говоря на высоте.
SYG>Опыт опыту — рознь, Я, благодаря интернету, знаю одного человека, который с Вами бы в этом вопросе сильно не согласился. В форуме на progz.ru он известен под ником ASU:
Ну давай его сюда. Пусть не соглашается.
SYG>А метода у него "простая": проектировать все сразу и, по возможности, без ошибок.
Он Бог? К томуже смотря на человечество я не уверен в том что Бог не совершает ошибок
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Если система автономная, то в ней, обычно, нет исходников — только бинарники. Кроме того в ней, обычно, нет подсистемы компилятора.
Дык что она делать то будет? В случае сбоя нужно как минимум поднять аварийную тревогу для того чтобы люди успели отреагировать пока не стало слишьком позно.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>А теперь, почувствуйте разницу, пример серьезного кода: SYG>
SYG>RESOURCESTRING
SYG> STORE_FILE_NAME_IS_EMPTY = 'Не задано имя инициализационного файла (StoreFileName = "")';
SYG>//------------------------------------------------------------------------------
SYG>CONST
SYG> IDENT_Form = 'Form';
SYG> IDENT_Left = 'Left';
SYG> IDENT_Top = 'Top';
SYG> IDENT_Width = 'Width';
SYG> IDENT_Height = 'Height';
SYG>//------------------------------------------------------------------------------
SYG>PROCEDURE TMainForm.Save;
SYG>VAR f: IniFiles.TIniFile;
SYG>BEGIN
SYG> f := NIL;
SYG> TRY
SYG> IF Self.FStoreFileName = ''THEN RAISE SysUtils.Exception.Create(STORE_FILE_NAME_IS_EMPTY);
SYG> IF SysUtils.FileExists(Self.FStoreFileName) THEN Windows.DeleteFile(PAnsiChar(Self.FStoreFileName));
SYG> TRY
SYG> f := IniFiles.TIniFile.Create(Self.FStoreFileName);
SYG> f.WriteInteger(IDENT_Form, IDENT_Left, Self.Left);
SYG> f.WriteInteger(IDENT_Form, IDENT_Top, Self.Top);
SYG> f.WriteInteger(IDENT_Form, IDENT_Width, Self.Width);
SYG> f.WriteInteger(IDENT_Form, IDENT_Height, Self.Height);
SYG> FINALLY
SYG> f.Free;
SYG> END;
SYG> EXCEPT ON e: SysUtils.Exception DO Error(e, 'TMainForm.Save') END
SYG>END;
SYG>//------------------------------------------------------------------------------
SYG>PROCEDURE TMainForm.Load;
SYG>VAR f: IniFiles.TIniFile;
SYG>BEGIN
SYG> f := NIL;
SYG> TRY
SYG> IF NOT SysUtils.FileExists(Self.FStoreFileName) THEN EXIT;
SYG> TRY
SYG> f := IniFiles.TIniFile.Create(Self.FStoreFileName);
SYG> Self.Left := f.ReadInteger(IDENT_Form, IDENT_Left, Self.Left);
SYG> Self.Top := f.ReadInteger(IDENT_Form, IDENT_Top, Self.Top);
SYG> Self.Width := f.ReadInteger(IDENT_Form, IDENT_Width, Self.Width);
SYG> Self.Height := f.ReadInteger(IDENT_Form, IDENT_Height, Self.Height);
SYG> FINALLY
SYG> f.Free;
SYG> END;
SYG> EXCEPT ON e: SysUtils.Exception DO Error(e, 'TMainForm.Load') END
SYG>END;
SYG>
Вообще, если исключение возникает в конструкторе, то деструктор вызывается автоматом.
Так как здесь f "заниляется", ничего страшного не будет. Но такой код хоть немного, но избыточен, а "серьезный" код, я думаю, этим грешить не должен.
Здравствуйте, Mystic, Вы писали:
M>Да, насколько мне известно (могу ошибаться), что в Black Box Oberon если не компилирировать в код Java VM, то память освобождается сразу же после того, как объект становитсья ненужным. Т. е. это не сборщик мусора в понимании .NET, это скорее подсчет ссылок как в интерфейсах в Delphi.
BlackBox — среда разработки и выполнения программ на языке Component Pascal созданная Oberon Microsystems работает под win32. BlackBox — не имеет отношения к Java и не имеет отношения к .NET. BlackBox — как среда поддерживающая компонентно ориентированную парадигму программирования имеет полноценный сборщик мусора — никаким подсчетом ссылок ее заменить в принципе невозможно (я тут уже обяснял почему — из-за возможных циклических ссылок объектов друг на друга). Раз уже зашла речь об отношениях между Оберонами и Java и .NET, то да, конечно существуют трансляторы Оберонов в Java, и существуют Обероны под .NET. (Сейчас разрабатывается клон Оберона — Zonnon будет работать под .NET)
А вообще, Обероны есть сами по себе (т.е. под ОС Оберон), под Linux, Solaris, MacOs X, Windows, Bluebottle. Скачивать можно отсюда: http://www.oberon.ethz.ch/download.html
Здравствуйте, WolfHound, Вы писали:
WH>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>Если система автономная, то в ней, обычно, нет исходников — только бинарники. Кроме того в ней, обычно, нет подсистемы компилятора. WH>Дык что она делать то будет? В случае сбоя нужно как минимум поднять аварийную тревогу для того чтобы люди успели отреагировать пока не стало слишьком позно.
Здравствуйте, WolfHound, Вы писали:
WH>Хм!? Разве масте-поинтеры это сложно? Я один раз потратил пол часа на реализацию мастер-поинтеров и теперь спокойно их использую. SYG>>То есть вынуждены будете напрягаться больше чем необходимо. И все это в топике "Серьезный код", в котором уже не раз подразумевалось, что серьезный код должен быть на столько простым на сколько это вообще возможно. WH>Вот именно. В базовой реализации просто не возможно предусмотреть все что может понадобится и код получится больше и сложнее. WH>Я пару раз расширял интерфейс своих мастер-поинтеров для того чтобы упростить их использование. Короче написав десяток строк я съекономил десятки тысячь строк. WH>Слабо сделать такое с тем что реализовано в языке?
WH>Я на счет finally это не в C++ при помощи автоматических деструкторов эмулируют finally, а в других языках при помощи finally эмулируют автоматические деструкторы. WH>Надеюсь не надо обьяснять почему код написаный однажды лучше кода написаного тысячи раз.
Например, в Component Pascal встроен сборщик мусора, там на мастер-поинтеры заморачиваться не надо в принципе. В чем состоит смысл Вашего замечания?
Re[3]: Пример не серьезного и аналогичного ему серьезного ко
Здравствуйте, _pk_, Вы писали:
__>Здравствуйте, S.Yu.Gubanov, Вы писали:
__>Вообще, если исключение возникает в конструкторе, то деструктор вызывается автоматом. __>Так как здесь f "заниляется", ничего страшного не будет. Но такой код хоть немного, но избыточен, а "серьезный" код, я думаю, этим грешить не должен.
Здравствуйте, WolfHound, Вы писали:
WH>Ну давай его сюда.
Как я его дам? Я с ним лично не знаком, даже не знаю как его зовут, знаю только его ник ASU и что он иногда бывает на progz.ru.
А я вот разделяю подход, который ув.С.Ю.Губанов безуспешно пытается донести
до всех вас. Более того! (тсссс) я и сам такой использую
Честно, хороший подход. А вы ему минусы, минусы...
SYG>>Вот и слава богу, что для такого способа решения задач он не предназначен! WH> Таких задачь огромное колличество. Вот я писал OPC серверы. Я бы повесился если бы в С++ небыло исключений.
Просто твой сервер использует отказо-не-устойчивый софт, поэтому ловить исключения нужно.
Это IMHO, но ты поведай, для чего конкретно (какие части сервера) ты использовал механизм исключений?
SYG>>Думаю, что ПО для электростанции под эту категорию подходит в самый раз. WH>А я писал софт для нефтяных заводов. Там надежность тоже должна быть мягко говоря на высоте.
(умалчивая)
SYG>>А метода у него "простая": проектировать все сразу и, по возможности, без ошибок. WH>Он Бог? К томуже смотря на человечество я не уверен в том что Бог не совершает ошибок
Скажем, надо так проектировать подсистемы, чтобы в них были предусмотрены все необходимые
виды ошибок-возвратов. Если же возникнет _настоящая_ _отловимая_ исключительная ситуация,
то надо просто вырубить/перезагрузить весь сбойный модуль (как блок), вернуть признак
ошибки тому, кто этот блок вызывал (если он не автономный был) и т.о. использовать
механизм исключений только для целых блоков, но никогда — для их содержания.
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>А я и не говорил что без механизма исключений будет проще или удобнее.
То есть ты соглашаешься с тем, что механизм программных исключений позволяет упростить обработку ситуаций, при которых программа не могла бы продолжить свое корректное выполнение? Дак зачем тогда добровольно отказываться от удобного механизма? Похоже просто на понты...
SYG>Я всего лишь говорил только то, что при наличии в системе сборщика мусора и "автостопа" при совершении "недопустимых операций" механизм возбуждения (кустарных, самодельных, пользовательских) исключений в принципе излишний.
Это всеравно, что заявить мол наличие метода для захвата ресурсов (напр. new) и метода для их освобождения (напр. delete) делают сборщик мусора излишним. А ведь действительно, если каждый выделенный ресурс не забывать освобождать, то сборщик мусора в принцепе не нужен Дак для чего же он тогда? Наверное, ДЛЯ УДОБСТВА! Вот и исключения тоже ДЛЯ УДОБСТВА!!!!
SYG>А мне пытались "впарить" что без механизма исключений ничего серьезного сделать вообще нельзя. Без него можно, но проектировать все нужно по другому
В принцепе, до Китая можно "раком" добежать. Пусть кто-нибудь докажет обратное
лэт ми спик фром май харт
Re[31]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, prVovik, Вы писали:
V>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>А я и не говорил что без механизма исключений будет проще или удобнее. V>То есть ты соглашаешься с тем, что механизм программных исключений позволяет упростить обработку ситуаций, при которых программа не могла бы продолжить свое корректное выполнение?
Что значит упростить? Как Вы себе представляете работу динамической многомодульной системы? Как исключение передать из одного (бинарного) модуля внутрь другого (бинарного) модуля, а из того в третий и т.д. Вы себе можете представить? Все модули, разумеется, от разных производителей. Я и не говорил что без механизма исключений проще или удобнее, я говорю что без механизма исключений — ПОДРУГОМУ.
SYG>>Я всего лишь говорил только то, что при наличии в системе сборщика мусора и "автостопа" при совершении "недопустимых операций" механизм возбуждения (кустарных, самодельных, пользовательских) исключений в принципе излишний. V> Это всеравно, что заявить мол наличие метода для захвата ресурсов (напр. new) и метода для их освобождения (напр. delete) делают сборщик мусора излишним. А ведь действительно, если каждый выделенный ресурс не забывать освобождать, то сборщик мусора в принцепе не нужен Дак для чего же он тогда? Наверное, ДЛЯ УДОБСТВА! Вот и исключения тоже ДЛЯ УДОБСТВА!!!!
Вот сколько ни объясняй что сборщик мусора вовсе не является прихотью или роскошью придуманной для ленивых программистов, все равно найдется кто-то кто так и не поймет! Что в этом такого сложного понять это??? Объясняю еще раз. Вот представьте себе что у Вас есть тысяча динамически загружаемых бинарных модулей все от разных производителей. Модули в процессе своей работы создают объекты (каждый модуль создает свои объекты). Для взаимодействия друг с другом эта тысяча модулей обмениваются друг с другом объектами (в виде полиморфных переменных). Объекты могут ссылаться друг на друга произвольным способом (то есть возможны циклические ссылки объектов из разных модулей друг на друга). КТО и КОГДА по Вашему должен вызывать delete для ненужных больше объектов? КАК узнать что объект больше никем не используется? Счетчик ссылок для этих целей не подходит так как возможны петлевые взаимоссылки. Учтите еще что на момент написания модуля НЕИЗВЕСТНО сколько и каких модулей еще будет в той ОС в которой он будет работать. Ну что? Дошло до Вас что задача вызова delete НЕРАЗРЕШИМА на момент написания модуля? Задача освобождения ресурсов может быть решена только ДИНАМИЧЕСКИ во время работы программы, а такая динамическая штуковина называется — СБОРЩИК МУСОРА.
SYG>Что значит упростить? Как Вы себе представляете работу динамической многомодульной системы? Как исключение передать из одного (бинарного) модуля внутрь другого (бинарного) модуля, а из того в третий и т.д. Вы себе можете представить? Все модули, разумеется, от разных производителей.
И в чем именно проблема?
В .Net-е, Java-е, скриптах, Smalltalk-е и т.д. — это проблема же как-то решается.
SYG>Вот сколько ни объясняй что сборщик мусора вовсе не является прихотью или роскошью придуманной для ленивых программистов, все равно найдется кто-то кто так и не поймет!
Замечу, что подсчет ссылок и сборщик мусора — это две дополняющие друг друга стратегии.
Подсчет ссылок лучше работает на малом кол-ве ссылок, сборщик мусора работает лучше на большом кол-ве ссылок.
В идеальном случае — лучше использовать и то, и другое, т.к. у подсчета ссылок — есть существенный плюс: правильный (детерминированный) момент времени освобождения ресурсов.
т.е. обобщенная стратегия, которая берут плюсы и минусы от обеих этих стратегий следующая:
считаем ссылки, но если ссылок стало слишком много переходим на сборщик мусора, также периодически сборщик мусора проверяет объекты с подсчетом ссылок, ищет циклы, и убивает их
Re[33]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, DarkGray, Вы писали:
SYG>>Что значит упростить? Как Вы себе представляете работу динамической многомодульной системы? Как исключение передать из одного (бинарного) модуля внутрь другого (бинарного) модуля, а из того в третий и т.д. Вы себе можете представить? Все модули, разумеется, от разных производителей.
DG>И в чем именно проблема?
Проблема в ответе на вопрос: "Что значит упростить?"
DG>В .Net-е, Java-е, скриптах, Smalltalk-е и т.д. — это проблема же как-то решается.
Java — интерпретатор (там может быть все что угодно), Smalltalk — не модульный, а в .Net встроен JIT компилятор — это явно не "упрощение", а "утяжеление".
DG>Замечу, что подсчет ссылок и сборщик мусора — это две дополняющие друг друга стратегии. DG>Подсчет ссылок лучше работает на малом кол-ве ссылок, сборщик мусора работает лучше на большом кол-ве ссылок. DG>В идеальном случае — лучше использовать и то, и другое, т.к. у подсчета ссылок — есть существенный плюс: правильный (детерминированный) момент времени освобождения ресурсов. DG>т.е. обобщенная стратегия, которая берут плюсы и минусы от обеих этих стратегий следующая: DG>считаем ссылки, но если ссылок стало слишком много переходим на сборщик мусора, также периодически сборщик мусора проверяет объекты с подсчетом ссылок, ищет циклы, и убивает их
Это уже детали реализации. Просто все еще находятся некоторые люди наивно полагающие что задачу освобождения ресурсов (каждому new свой delete) можно решить в момент написания модуля программы. В общем случае эта задача статически неразрешима и для ее решения надо использовать динамические методы, причем одного лишь подсчета ссылок в общем случае будет недостаточно (например, два объекта ссылающихся друг на друга можно удалить только если есть полноценный сборщик мусора.)
Здравствуйте, Demiurg, Вы писали:
D>Здравствуйте, AndreyFedotov, Вы писали:
AF>>>>для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
AR>>>А вот это бы я назвал именно сложным кодом.
AF>> Иногда да, иногда нет. В таких системах часто сам код очень простой, но именно наличие множества скрытых и не очевидных связей делает его написание делом не простым.
D> Может просто проблема проектирования? Код должен быть простым для понимания, тогда это хороший код. Смотря, конечно, для кого простым На асме писать очень просто, но при сложном алгоритме (да и просто по мере разбухания проекта, если его правильно не спроектировать) получается как раз такой "серьезный", по-твоему определению, код. На ЯВУ же этого запутывания имхо можно избежать.
Теоретически да. Практически, когда происходит упрощение кода, то (если код спроектирован и написан хорошо ) часто происходит добавление новых уровней абстракции и сущностей (что собственно и позволяет упростить код). Если чепловек с этими понятиями и моделями знаком — то для него код упрощается. Если же не знаком (что бывает гораздо чаще), то хотя каждая часть кода по отдельности возможно и стала проще — но код в целом может стать даже сложнее.
Простой пример. В своё время иногда писали на диск используя прерывания и аппаратуру контроллера. Код был довольно навороченным (прописывалась куча регистров и т.д.), но его суть очень проста. Если взять код, который пишет в файл под Windows — код будет гораздо яснее, очевиднее и проще. Но это только в том случае, если рассматирвать только клиентскую часть кода. А если рассматиривать и саму ОС — работу её кода, то всё стало намного сложнее и требует гораздо больше времени для понимания.
То же бывает и в других многоуровневых системах.
Здравствуйте, Glоbus, Вы писали:
G>Здравствуйте, AndreyFedotov, Вы писали:
G>я лично думаю, что формулировка плохая. Нет понятия серьезный код или несерьезный, как мнекажется. Есть понятие "серьезная задача".
Полностью согласен. Вопрос задал потому — что эта формулировка возникала слишком часто...
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Denwer, Вы писали:
D>>Серьезность кода и диплом не имееют ничего общего, по крайней мере везде где я знаю так оно и есть. Я знаю такие дипломные работы, котрые даже на лабораторную для 1-ого курса не потянут. А код которых и глядеть страшно.
D>>ЗЫ: Исключения бывают конечно, но это именно исключения, а не правила. LVV>Ну так у нас сплошные исключения
Или сплошные изверги...
Re[32]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
SYG>Что значит упростить? Как Вы себе представляете работу динамической многомодульной системы? Как исключение передать из одного (бинарного) модуля внутрь другого (бинарного) модуля, а из того в третий и т.д. Вы себе можете представить? Все модули, разумеется, от разных производителей. Я и не говорил что без механизма исключений проще или удобнее, я говорю что без механизма исключений — ПОДРУГОМУ.
Ну в Windows'e же есть SEH! Вы скажете, что типа Windows — это не модульная ось, а потому там все подругому, или что-то в этом роде. Я не буду с вами спорить в этом вопросе, а только замечу, что любое поведение исключений всегда можно сэмулировать через коды возврата. Вы всем предлагаете делать это ВРУЧНУЮ. Да, действительно, это сделать можно, но это НЕУДОБНО. Мне, как программисту значительно удобней, когда это сделает компилятор
автоматически. В этом и заключается удобство. Я не вижу принципиальной разницы между исключениями и кодами возврата и я не понимаю, почему модули могут работать через коды возврата и не могут через исключения. В заключается неразрешимая проблема?
SYG>Вот сколько ни объясняй что сборщик мусора вовсе не является прихотью или роскошью придуманной для ленивых программистов, все равно найдется кто-то кто так и не поймет!
Это вы о ком? Случайно не обо мне? Что-то я не припоминаю за собой таких слов...
Я лишь говорил, что ТЕОРЕТИЧЕСКИ можно обойтись без сборщика мусора, точно так, как можно обойтись без исключений. Но в том и в другом случае это неудобно.
SYG>Что в этом такого сложного понять это??? Объясняю еще раз. Вот представьте себе что у Вас есть тысяча динамически загружаемых бинарных модулей все от разных производителей. Модули в процессе своей работы создают объекты (каждый модуль создает свои объекты). Для взаимодействия друг с другом эта тысяча модулей обмениваются друг с другом объектами (в виде полиморфных переменных). Объекты могут ссылаться друг на друга произвольным способом (то есть возможны циклические ссылки объектов из разных модулей друг на друга). КТО и КОГДА по Вашему должен вызывать delete для ненужных больше объектов? КАК узнать что объект больше никем не используется? Счетчик ссылок для этих целей не подходит так как возможны петлевые взаимоссылки. Учтите еще что на момент написания модуля НЕИЗВЕСТНО сколько и каких модулей еще будет в той ОС в которой он будет работать. Ну что? Дошло до Вас что задача вызова delete НЕРАЗРЕШИМА на момент написания модуля? Задача освобождения ресурсов может быть решена только ДИНАМИЧЕСКИ во время работы программы, а такая динамическая штуковина называется — СБОРЩИК МУСОРА.
Ой, сколько эмоций!
Вы понимаете, что в основе любого сборщика мусора лежит все тот же детерминированный вызов оператора delete? Вас это ни на какие мысли не наталкивает? Не кажется ли вам, что работа сборщика мусора может быть просто сэмулирована точно так, как вы предлагаете эмулировать обработку исключений через коды возврата? Выражаясь вашим языком, просто надо проектировать такую систему ПОДРУГОМУ. Да, это геморрой, да сборщик мусора — это хорошо, удобно и сладко, впрочем, так же как и исключения...
лэт ми спик фром май харт
Re[33]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, prVovik, Вы писали:
V>Я не вижу принципиальной разницы между исключениями и кодами возврата.
Исключения бывают двух сортов:
1) Псевдоисключения, которые вовсе никакие не исключения, а Ваши собственные доморощенные штуки, которые Вы используете как продвинутые коды возврата. Между ними и кодами возврата действительно нет никакой принципиальной разницы, а значит они в языке программирования в принципе излишни.
2) Истинные исключения, то есть те которые имеют свое происхождение от прерываний генерируемых процессором. Например, прерывание INT 0 — деление на ноль. По другому, "истинные исключения" можно назвать "недопустимые операции". Если программа совершает "недопустимую операцию", то она должна быть остановлена как не имеющая смысла.
Впрочем, если Вы не видите разницы, ну и не надо, мне не жалко. Если Вы полагаете что механизм исключений введен в язык только для удобства, а не потому что без этого механизма теоретически невозможно писать серьезные программы, то я согласен с Вами. Исключения — сами по себе излишни, можно обойтись и без них — вот моя точка зрения. Кажется наши точки зрения по этому пункту совпадают.
А вот по следующему пункту наши точки зрения противоположны: V>Я лишь говорил, что ТЕОРЕТИЧЕСКИ можно обойтись без сборщика мусора
А Я лишь говорил, что в модульных системах без сборщика мусора обойтись ТЕОРЕТИЧЕСКИ нельзя.
И что дальше будем делать? Вы мне говорите "теоретически можно", а я Вам говорю "теоретически нельзя", и так до бесконечности будем, кто кого переговорит?
Предлагаю Вам решить такую задачу:
Вы являетесь автором одного динамически загружаемого модуля. Этот модуль создает объекты и отдает указатели на них другим динамически загружаемым модулям (другие модули написаны другими производителями, и у Вас есть/будут только их бинарники). На момент написания своего модуля Вы даже точно не знаете какие именно будут те самые другие модули. Как Вы будете принимать решение об уничтожении созданных в Вашем модуле объектов? Как Вы узнаете что созданный Вашим модулем объект больше никем не используется?
Re[34]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Исключения — сами по себе излишни, можно обойтись и без них — вот моя точка зрения. Кажется наши точки зрения по этому пункту совпадают.
Нет, не совсем. Я уже писал, что без исключний теоретически можно обходиться, но это неудобно. Приходится писать более громоздкий код, который сильнее подвержен ошибкам. Вот что пишет Страуструп об исключениях:
Автор библиотеки может обнаружить ошибки времени выполнения, но, в общем случае, не имеет ни малейшего представления что с ними делать. Пользователь библиотеки может знать как бороться с такими ошибками, но не может их обнаружить — в противном случае они бы обрабатывались в коде пользователя, и их обнаружение не было бы возложено на библиотеку. Для помощи в решении подобных проблем введено понятие "исключения". Фундаментальная идея состоит в том, что функция, обнаружившая проблему, но не знающая как ее решить, генерирует исключение в надежде, что вызвавшая ее(непосредственно или косвенно) функция сможет решить возникую проблему. Функция, которая хочет решать проблемы данного типа, может указать, что она перехватывает такие исключения.
SYG>Предлагаю Вам решить такую задачу: SYG>Вы являетесь автором одного динамически загружаемого модуля. Этот модуль создает объекты и отдает указатели на них другим динамически загружаемым модулям (другие модули написаны другими производителями, и у Вас есть/будут только их бинарники). На момент написания своего модуля Вы даже точно не знаете какие именно будут те самые другие модули. Как Вы будете принимать решение об уничтожении созданных в Вашем модуле объектов? Как Вы узнаете что созданный Вашим модулем объект больше никем не используется?
Да хотябы вот так вот: http://www.rsdn.ru/article/cpp/GCcpp.xml
Здравствуйте, prVovik, Вы писали:
V>Я уже писал, что без исключний теоретически можно обходиться, но это неудобно.
Удобно или не удобно это уже другой вопрос...
SYG>>Предлагаю Вам решить такую задачу: SYG>>Вы являетесь автором одного динамически загружаемого модуля. Этот модуль создает объекты и отдает указатели на них другим динамически загружаемым модулям (другие модули написаны другими производителями, и у Вас есть/будут только их бинарники). На момент написания своего модуля Вы даже точно не знаете какие именно будут те самые другие модули. Как Вы будете принимать решение об уничтожении созданных в Вашем модуле объектов? Как Вы узнаете что созданный Вашим модулем объект больше никем не используется?
V>Да хотябы вот так вот: http://www.rsdn.ru/article/cpp/GCcpp.xml
Да ничего подобного! Вы дали ссылку на решение задачи для случая когда вся программа состоит всего из одного модуля (скомпилирована в один единственный огромный и монолитный exe-шник), а я все время говорю о модульных программах, то есть программах состоящих, быть может, из нескольких тысяч динамически загружаемых модулей. Давайте внимательно прочитаем задание: SYG>>Вы являетесь автором одного динамически загружаемого модуля. Этот модуль создает объекты и отдает указатели на них другим динамически загружаемым модулям (другие модули написаны другими производителями, и у Вас есть/будут только их бинарники).
Как организована ваша приватная внутримодульная утилизация более не используемых ресурсов — Ваше личное дело и оно не интересует другие модули (можете даже использовать для этого ту ссылку которую привели). Вопрос состоит в другом — как Вы будете принимать решение об уничтожении объектов адреса которых Вы сообщали другим (внешним) модулям?
В той ссылке описывается доморощенный сборщик мусора работающий только внутри одного модуля. То есть если запустить два экземпляра такой программы, то, соответственно, будет два доморощенных сборщика мусора. Две таких программы не смогут обмениваться объектами друг с другом. Я же говорю об одном единственном на всю ОС сборщике мусора который единолично разруливает все объекты всех модулей системы. В Component Pascal, .NET и Java сборщик мусора всего один на всю систему независимо от того сколько программ (модулей) в этой системе в данный момент загружено. Так понятно?
Re[36]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Вы дали ссылку на решение задачи для случая когда вся программа состоит всего из одного модуля (скомпилирована в один единственный огромный и монолитный exe-шник)
Я дал эту ссылку для того, чтобы показать технологию эмулирования сборщика мусора. Я думал, что вы догадаетесь, что по тому же принципу можно сделать и разделяемый сборщик мусора. В чем проблема?
лэт ми спик фром май харт
Re[37]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, prVovik, Вы писали:
V>Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>>Вы дали ссылку на решение задачи для случая когда вся программа состоит всего из одного модуля (скомпилирована в один единственный огромный и монолитный exe-шник) V>Я дал эту ссылку для того, чтобы показать технологию эмулирования сборщика мусора. Я думал, что вы догадаетесь, что по тому же принципу можно сделать и разделяемый сборщик мусора. В чем проблема?
Даже не знаю что и ответить. Действительно, а в чем собственно проблема-то? Всего-то навсего надо написать свой собственный эмулятор ОС (или, на худой конец, свою виртуальную машину) со сборщиком мусора и линковщиком для динамической загрузки модулей. Тяп ляп и готово. Работы на полчаса...
До сих пор проблема была в том, что Вы утверждали, что сборщик мусора в принципе не нужен, а нужен только для удобства, а я пытался убедить Вас в том что он нужен вовсе не для удобства, а в принципе чтобы писать модульные программы, так как модульные программы без него писать невозможно.
Re[34]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
DG>>В .Net-е, Java-е, скриптах, Smalltalk-е и т.д. — это проблема же как-то решается.
SYG>Java — интерпретатор (там может быть все что угодно), Smalltalk — не модульный, а в .Net встроен JIT компилятор — это явно не "упрощение", а "утяжеление".
Простите, а почему это Smalltalk не модульный?
... << RSDN@Home 1.1.3 stable >>
Re[38]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>До сих пор проблема была в том, что Вы утверждали, что сборщик мусора в принципе не нужен, а нужен только для удобства, а я пытался убедить Вас в том что он нужен вовсе не для удобства, а в принципе чтобы писать модульные программы, так как модульные программы без него писать невозможно.
Возникает вопрос, а нужно ли писать модульные программы вообще ? (Модульные — в вашем понимании, а то сюдя по вашим репликам, во всех остальных языках ничего подобного сделать нельзя.)
Душа обязана трудиться! (с) Н.Заболоцкий.
Re[38]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG> Всего-то навсего надо написать свой собственный эмулятор ОС (или, на худой конец, свою виртуальную машину) со сборщиком мусора и линковщиком для динамической загрузки модулей. Тяп ляп и готово. Работы на полчаса...
Во-первых, я не говорил, что будет легко . Во-вторых, не надо никаких осей, машин и пр. Достаточно лишь обязать все модули работать с разделяемым сборщиком мусора.
SYG>До сих пор проблема была в том, что Вы утверждали, что сборщик мусора в принципе не нужен, а нужен только для удобства, а я пытался убедить Вас в том что он нужен вовсе не для удобства, а в принципе чтобы писать модульные программы, так как модульные программы без него писать невозможно.
Стоп, все было не совсем так Я говорил, что при отсутствии встроенного сборшика мусора его работу теоретически можно сэмулировать стандартными средствами. Вот цитата:
Вы понимаете, что в основе любого сборщика мусора лежит все тот же детерминированный вызов оператора delete?... Не кажется ли вам, что работа сборщика мусора может быть просто сэмулирована
Вы же начали протестовать...
Я вас убедил в том, что можно решить вашу задачу на С++, несмотря на то, что в С++ нет сборшика мусора?
лэт ми спик фром май харт
Re[39]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, prVovik, Вы писали:
V>Я вас убедил в том, что можно решить вашу задачу на С++, несмотря на то, что в С++ нет сборшика мусора?
Для одного отдельно взятого модуля, для его внутренних объектов, адреса которых он внешним модулям не сообщал, теоретически можно во время написания модуля расставить все delete и вообще забить на сборщик мусора. Для многомодульных программ сама среда исполнения должна обладать сборщиком мусора.
SYG> Всего-то навсего надо написать свой собственный эмулятор ОС (или, на худой конец, свою виртуальную машину) со сборщиком мусора и линковщиком для динамической загрузки модулей. Тяп ляп и готово. Работы на полчаса... V>Во-первых, я не говорил, что будет легко . Во-вторых, не надо никаких осей, машин и пр. Достаточно лишь обязать все модули работать с разделяемым сборщиком мусора.
Я говорю, что в модульных системах обязательно должен быть единый сборщик мусора, а Вы в ответ говорите, что нет, ничего подобного, сборщика мусора не надо, а "достаточно лишь обязать все модули работать с разделяемым сборщиком мусора". Приехали...
Re[35]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Для одного отдельно взятого модуля, для его внутренних объектов, адреса которых он внешним модулям не сообщал, теоретически можно во время написания модуля расставить все delete и вообще забить на сборщик мусора. Для многомодульных программ сама среда исполнения должна обладать сборщиком мусора.
Можно ли динамически загружаемую длл считать динамически загружаемым модулем? И если нет то почему?
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[41]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, WolfHound, Вы писали:
WH>Можно ли динамически загружаемую длл считать динамически загружаемым модулем? И если нет то почему?
Модуль — это абстракция языка программирования. После компиляции, модуль имеет физическое представление, например, пускай в виде DLL файла. Но, дело в том, что обычную Win32 DLL называть скомпилированным модулем как-то не очень хорошо, ведь в Win32 DLL не содержится подробной информации о типах, а в модуле она содержится.
Из хелпа к BlackBox-у:
When compiling a module, the compiler produces a code file and a symbol file. The code file contains the executable code, which can be loaded into memory. The code file is a kind of super-lightweight DLL. The compiler also produces a symbol file, which contains a binary representation of the module's interface. If a module imports other modules, the compiler reads the symbol files of all these modules, in order to check that their interfaces are used correctly.
Таким образом, в BlackBox-е модуль после компиляции физически представляется двумя бинарными файлами: symbol file — там хранится бинарное представление типов, так сказать бинарный эквивалент "заголовочного файла"; и code file — super-lightweight DLL.
А, например, в .NET-е после компиляции модуль физически представляется одним бинарным файлом в котором есть и код и информация о типах.
Я считаю что серьезный код зависит от задачи и если от нее плясать то, серьезный код- это код который при изменении задачи или её расширении, дополнении придется минимально расширять + не менять логику програмы в корне.
Re[42]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Но, дело в том, что обычную Win32 DLL называть скомпилированным модулем как-то не очень хорошо, ведь в Win32 DLL не содержится подробной информации о типах, а в модуле она содержится.
Не очень хорошо но в принципе можно? А если еще к дллке приложить заголовочный фаил с описанием типов для того чтобы можно было компилить другие дллки? А можно ли назвать модулем дллку которая предоставляетописание интерфейсов и несколько фабрик классов которые порождают объекты классов реализующих эти интерфейсы?
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[41]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, WolfHound, Вы писали:
WH>Можно ли динамически загружаемую длл считать динамически загружаемым модулем? И если нет то почему?
Есть все же разница между возможностью создания на языке динамически загружаемых библиотек. И модульной архитектурой языка.
Когда заходит речь о немодульности С++, то речь идет о том, что импорт типов в С++ делается самым глупым и непроизводительным образом — инклюдами. Т.е. по сути импорта как такового нет. Есть обязательное предворительное объявление (предекларация) используемых типов в текстовм виде. И некоторый макросный механизм по подстановке содержимого одного файла в другой.
В отличие от этого убого подхода истинно модельные системы оперируют бинарными (скомпилированными) модулями хранящими метоинформацию об экспортируемых типах. Такую информацию очень легко и быстро читать и для этого не требуется ни механизмов текстовой подстановки, ни долгого процесса парсинга.
Как показала практика С++ не спасает даже прекомпилируемые хэадеры. Скорость компиляции VC в десятки раз медленнее шарпа (а то и больше). Это прямое следствие не модульности С++. Причем совсем не ясно почему нельзя добавить модульность в С++. Концепции языка это вроде изменить не дожно. Если только шаблоны затронет.
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[42]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>А, например, в .NET-е после компиляции модуль физически представляется одним бинарным файлом в котором есть и код и информация о типах.
Странно... ну и толку от информации о типах то? Почему модули это то что есть бинарник(любого вида) + информация о типах?
Если наша задача требует модульности... (например ОС Windows сама по себе нуждается в ней и приложения которые под нее написаны ее используют), но именно в том виде в котором она существует. Для того что бы бинарный код общался между собой они должны следовать одному и тому же протоколу, и... и модули в том же виндовз можно _динамически_ загружать и _выгружать_. Учет ссылок и выделенных ресурсах при этом (как и в любых неуправлямых средах) лежит на нас. Поэтому говорить о том что там это нельзя, а здесь можно, просто глупо. На универсальных языках можно все — вот вопрос хотим ли мы писать среду выполнения для себя... вот это уже другой вопрос. Хотя как я заметил как правило любой более-менее большой продукт имеет какие-то управляющие примитивы в run-time
В конце концов... какие-нибудь серверы которые работают 24х7 — довольно критичны к падениям. Возьми любой из Apache. Что? Глючит? А если и заглючит, думаешь упадет? Ну завалить оооочень сложно. А если есть критичность ко всем "завалам" так один клиент на процесс (что настраивается просто в конфиге, просто медленнее работать будет — и ты просто не сможешь нарушить работу других клиентов)... так что надежность по разному реализовать можно. А модуль — выполнен оказался как процесс. в моем примере... ес-сно
За это я и люблю программирование Тут все можно с ног на уши поставить
... << RSDN@Home 1.1.4 beta 2 >>
Re[36]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали
SYG>Не знаю. Наверное ему просто не повезло. Хотя как знать, как знать...
Хм... А если говорить по существу?
Я, например, работаю в VisualWorks Smalltalk. В нем есть такая единица распространения скомпилированного кода, как парсел (parcel). Парсел включает в себя классы (и даже может включать методы классов, не входящих в данный парсел ). Код в парселе хранится в скомпилированном виде (исходники тоже могут идти с парселем, но в отдельном файле).
Также в парселе хранится и мета-информация (например, список определенных в нем классов).
Парсел может быть программно загружен и выгружен. После загрузки парсела определенные в нем классы (методы, переменные и т. д.) становятся доступны в системе.
Так вот, мой вопрос, собственно, таков: можно ли парсел назвать модулем?
И если нет, то почему?
... << RSDN@Home 1.1.3 stable >>
Re[37]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, serg_mo, Вы писали:
_>Хм... А если говорить по существу? _>Я, например, работаю в VisualWorks Smalltalk. В нем есть такая единица распространения скомпилированного кода, как парсел (parcel). Парсел включает в себя классы (и даже может включать методы классов, не входящих в данный парсел ). Код в парселе хранится в скомпилированном виде (исходники тоже могут идти с парселем, но в отдельном файле). _>Также в парселе хранится и мета-информация (например, список определенных в нем классов). _>Парсел может быть программно загружен и выгружен. После загрузки парсела определенные в нем классы (методы, переменные и т. д.) становятся доступны в системе.
_>Так вот, мой вопрос, собственно, таков: можно ли парсел назвать модулем? _>И если нет, то почему?
А, ну если так, то прошу прощения. Общипся я.
Re[43]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, WolfHound, Вы писали:
SYG>>Но, дело в том, что обычную Win32 DLL называть скомпилированным модулем как-то не очень хорошо, ведь в Win32 DLL не содержится подробной информации о типах, а в модуле она содержится.
WH>Не очень хорошо но в принципе можно? А если еще к дллке приложить заголовочный фаил с описанием типов для того чтобы можно было компилить другие дллки?
Скажем так, модулем называется некая абстракция (среды программирования), а "dll-ка + заголовочный файл" — это одна из реализаций этой абстракции. Если у Вас есть только "dll-ка + заголовочный файл", но нет среды программирования поддерживающей абстракцию модуля, то это так и останется "dll-кой + заголовочный файл" и модулем оно не станет.
WH>А можно ли назвать модулем дллку которая предоставляетописание интерфейсов и несколько фабрик классов которые порождают объекты классов реализующих эти интерфейсы?
Совершенно по барабану что внутри дллки.
Re[42]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, VladD2, Вы писали:
VD>Причем совсем не ясно почему нельзя добавить модульность в С++. Концепции языка это вроде изменить не дожно. Если только шаблоны затронет.
Шаблоны + inline функции + обратная совместимость с Си + все старые программы надо будет переделать так как надо будет перед некоторыми переменными и именами функций написать имя модуля в котором они объявлены. Выгоднее создать новый язык чем пытаться вносить модульность в существующий С++. Наверное, из-за этого и появился C#.
Re[43]: Задача вызова delete НЕРАЗРЕШИМА на момент написания
Здравствуйте, S.Yu.Gubanov, Вы писали:
SYG>Шаблоны + inline функции + обратная совместимость с Си + все старые программы надо будет переделать так как надо будет перед некоторыми переменными и именами функций написать имя модуля в котором они объявлены.
Ничего подобного. С++ обладает всеми нужными фичами по определению области видимости. В том же МС++ добавили всего одну директиву "#import" позволившую сделать из С++ модульный язык. При это оставили даже возможность инклюдить все как раньше.
SYG> Выгоднее создать новый язык чем пытаться вносить модульность в существующий С++. Наверное, из-за этого и появился C#.
Ну, Шарп сделали как новый язык в котором попытались совместить общую продуманность и простоту. Он даже клоном С++ не является.
... << RSDN@Home 1.1.4 beta 2 >>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, IPv6, Вы писали:
IP>О! настальгия... между прочим асм там был ничего. даже недокументированные команды были! И какие!
Ты случаем ностальгически не слушаешь программы Z80 через магнитофон? А то у меня где-то завалялись чудные записи.
Здравствуйте, AndreyFedotov, Вы писали:
IT>>Не знаю какой код можно назвать "серьёзным", но вот "пальцастым" называется код, который пишут только настоящие пацаны
AF> А какой код пишут "настоящие пацаны"? Кстати на чём? С? С++? C#? Ещё что то более пацанское?
Настоящие пацаны пишут на С, С++, C#.
А настоящие профессионалы юзают ФОРТ!
Ибо так оно и есть.
Здравствуйте, DJ KARIES, Вы писали:
DK>Настоящие пацаны пишут на С, С++, C#. DK>А настоящие профессионалы юзают ФОРТ! DK>Ибо так оно и есть.
Скорее строго наоборот.
Здравствуйте, Denwer, Вы писали:
AF>> Подумав над данным вопросом сам, пришёл к выводу, что для меня "серъёзный" код — это код со сложной архитектурой и множеством взаимосвязей и взаимозависимостей.
D>Это хреновый код который не поддается пониманию и рефакторингу, такой код обычно выбрасывается на помойку после ухода программиста, писавшего его.
Знаете как хорошо было бы, если бы заказчики именно так и делали?
Здравствуйте, GlebZ, Вы писали:
GZ>Здравствуйте, DJ KARIES, Вы писали:
DK>>Настоящие пацаны пишут на С, С++, C#. DK>>А настоящие профессионалы юзают ФОРТ! DK>>Ибо так оно и есть. GZ>Скорее строго наоборот.
Да, воистину пацаны телескопами рулят!
Ибо Чарльз Мур!