стиль программирования
Когда я заботаю C++ для чайников - второе, наверное.
Второе, правда я нифига не программист.
какое мне больше нравится или какое я признаю более целесообразным?
Эти функции не эквивалентны.
Но модуль-то в общем случае работать будет, я так понимаю.
второй очевидно более информативен на стадии отладки, а вообще... вообще это ж совсем разные функции!
Судя по первым каментам народ не прохавал. Дальше функции совершенно одинаковые, возможно очень длинные. Что-то делают. Различаются только первой строкой.
А функция обязательно void?
1-й вариант лучше... по крайней мере, мне понятней больше, нежели во втором... не дружу с ассертами
я бы на exceptions сделал
хотя - дело вкуса...
в одном случае будет ретурн и прога продолжит работу, в другом ассерт вылетит.Спасибо, что объяснил разницу.
Смысл в том, что первый вариант с одной стороны более устойчивый. С другой стороны он прячет ошибки.
Предположим, что язык этого не поддерживает. В данном случае это просто C.
В первом варианте нулл на входе в порядке вещей, во втором — невероятное событие.
Я не хотел менторствовать , просто в таких ограничениях всеми силами отстаиваю второй способ
Окей, поясню. Будем считать, что API озвучивается следующим образом:
A call to somefunc must be supplied with a valid struct abc * pointer.
voidsomefunc(struct abc *abcp, int i)
{
ASSERT(abcp != NULL, "%s: achtung! abcp is NULL", __func__);
if (abcp == NULL)
return;
> A call to somefunc must be supplied with a valid struct abc * pointer.
Одно дело, если сразу было такое требования.
Другое дело, когда к нему пришли в процессе развития проекта, и возможно, что какие-то другие модули считают нормальным передавать NULL.
Тогда ответ — второй вариант, т.к. не требует озвучивания API. Первый вариант только смущает читающего.
Смысл в том, что первый вариант с одной стороны более устойчивый. С другой стороны он прячет ошибки.Я бы предпочёл несколько другой вариант - примерно как:
if(some_error)
{
report_err_message("Fuck! Error at function somefunc! Pointer is NULL.", ERROR_LEVEL__JUST_WARNING, "error class a");
return;
}
где report_err_message - некоторая функция, которую можно переопределить по ситуации, и которая выводит куда-то сообщение, если ранг ошибки выше чего-то, а то, куда выводит - определяется классом ошибки.
Можно наворотить ещё дальше - сделать чтобы функция возвращала что-то, на основаннии чего программа решала бы, продолжать работу ей, сделать return или бросить исключение (но такая программа громоздкой получается).
Чем хорош такой подход - ошибки не прячутся, если есть потребность, можно разделить ошибки на классы ошибок, работает на любом языке программирования (ну почти на любом).
тогда уж надо бы посмотреть, а не пора ли сразу соответствующими эксепшнами кидаться вместо такой громоздкой конструкции? (в случае, конечно, С++)
Я бы предпочёл несколько другой вариант - примерно как:Ну да, это наилучший вариант, если заведомо известно, что есть пидарасы, которую будут звать функцию с неверными аргументами.
if(some_error)
{
report_err_message("Fuck! Error at function somefunc! Pointer is NULL.", ERROR_LEVEL__JUST_WARNING, "error class a");
return;
}
http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/52691
Конкретно этот вылился вот в такую дискуссию:
http://lists.freebsd.org/pipermail/freebsd-bugs/2003-May/000966.html
А к такому подходу я пришёл на платформах, где исключений нет (в первую очередь - на php, хотя на c++ также делаю). Мне он нравится тем, что с одной стороны - гибкий, с другой стороны - переносимый.
В таком случае однозначно второй, причём с ассертом, который будет компилиться и в релизе.
Вылетевшая прога гораздо лучше, чем прога, похерившая базу в результате тотального слёта крыши.
Прога, вылетевшая с вменяемым объяснением гораздо лучше проги, вылетевшей молча (и несравнимо лучше проги со съехавшей крышей, похерившей базу и вылетевшей в произвольном месте).
В таком случае однозначно второй, причём с ассертом, который будет компилиться и в релизе.Ага. Собственно мне интересно, сколько людей думают так же как я.
Вылетевшая прога гораздо лучше, чем прога, похерившая базу в результате тотального слёта крыши.
Прога, вылетевшая с вменяемым объяснением гораздо лучше проги, вылетевшей молча (и несравнимо лучше проги со съехавшей крышей, похерившей базу и вылетевшей в произвольном месте).
ненавижу программы - которые падают полностью (перестают работать полностью) - из-за мелкой ошибки в неважном модуле.
Думаю, любую программу, падающую полностью из-за мелких ошибок, можно отладить до такой степени, чтобы таких ошибок не было. А вот программу, которая из-за мелкой ошибки в неважном модуле делает что угодно, отладить уже гораздо сложнее, да и последствия такого в готовом продукте гораздо хуже.
Ставь на границах между логическими модулями трай-котчи.
В языках без ексепшенов, к сожалению, ошибка либо сразу корректно обрабатывается, либо роняет прогу целиком (причём тут на выбор два варианта - сразу и безболезненно, или потом и после долгих мучений).
Кстати, прочитал предложение, из-за которого дискуссия - сделать cmpstr тихо выдающим 0 если хотя бы один из параметров - нулл, и почему-то вспомнился Программист на Дельфе Вася.
Неплохой вариант, кстати.
В языках без ексепшенов, к сожалению, ошибка либо сразу корректно обрабатывается, либо роняет прогу целиком (причём тут на выбор два варианта - сразу и безболезненно, или потом и после долгих мучений).Ядро, обнаружив ошибку в файловой системе, может отключить эту одну файловую систему (или перемонтировать в r/o). Целиком ОС при этом не падает.
запускать cmpstr отдельным процессом? =)
Если-бы не плохая интеграция python'а с апачем, писал бы на питоне.
Ну да. Уверен, там эта ситуация отдельно отрабатывается.
даже в языках без exception-он можно протащить ошибку наверх.
аварийный выход из программы - обычно всегда означает, что программисту просто было лень думать, как осуществить работу с ошибками в его модуле.
Джава и АСП нынче не котируются?
А разве в 5-ом пхп нету ексепшенов?
Да и если уж тебя волнует одна интеграция питона с апачем - напиши ее сам, через CGI хотя бы. Благо там не ахти как сложно.
Отключение модуля == корректная обработка.
пхп подгружается как модуль. Меня не устраивает то, что для кадого запроса создаётся новый процесс.
А CGI-приложения на питоне написать не сложно, да и модуль есть.
Я, как правило, пишу просто
if (p == NULL) abort;
Это если userland-код, и лень думать, как правильно восстанавливаться,
или, что чаще, восстановление бессмысленно или невозможно.
Да, естественно, можно даже полностью написать свой аналог SEH, но сейчас же речь идёт о том, что функция тихо возвращает корректное значение =)
и даже в такой ситуации программа должна вести себя корректно,
аварийный выход - это некорректное поведение.
Программа не может вести себя корректно, если она не знает, что произошла ошибка. Точка.
какого фига программист разработал сигнатуру функции, которую не поддерживает возврат ошибок?
> и даже в такой ситуации программа должна вести себя корректно,Большой класс задач - обработка каких-то массивов данных. Вот, сбой при обработке отдельного элемента не должен приводить к сбою программы, то есть в норме (в большинстве числе случаев) нужно бросить этот отдельный элемент и обрабатывать дальше. Поэтому никаких абортов. А на более высоком уровне программа, анализируя процент ошибок, может уже принимать решение, прерываться, или забивать на ошибки. Но при этом логи - нужны.
Программа не может вести себя корректно, если она не знает, что произошла ошибка. Точка.
из samba4
/*
this module uses a fork per gethostbyname call. At first that
might seem crazy, but it is actually very fast, and solves many of
the tricky problems of keeping a child hanging around in a library
(like what happens when the parent forks). We use a talloc
destructor to ensure that the child is cleaned up when we have
finished with this name resolution.
*/
+1
сейчас же речь идёт о том, что функция тихо возвращает корректное значение
в начальном посте - функция, вобще-то, ничего не возвращает.
Да, можно ещё модули запускать отдельными процессамиО да! Я еще участвовал в обсуждении замечательной идеи ловить SIGSEGV и снимать тот тред, который облажался
смотря как реализованы остальные классы в системе, главное, чтоб везде было одинаково, например выскакивало бы исключение с сообщением об ошибке
+1
А вот мне плохо понятно, какая в С имеется альтернатива исключениям? Если пишешь какую-то библиотеку самого нижнего уровня, которая ни на что кроме ОС не опирается, то вроде можно перечислить все ошибки в каком нибудь enum-е error_t и их из каждой функции возвращать. Исключение, правда, помимо своего типа еще и данные может нести, ну да бог с ним.
> я бы на exceptions сделал
Предположим, что язык этого не поддерживает. В данном случае это просто C.
Но если программа большая, модуль A вызывает модуль B, а тот в свою очередь вызывает модуль C, то каким образом B рассказывает A про ошибки, произошедшие в C? Что, каждый раз, когда расширяется c_error_t надо расширять b_error_t, и писать отображение из первого во второе? А, или еще битовыми масками можно разрулить, если старший бит взведен, значит ошибка была в C, и в остальных битах идет c_error_t, а если не взведен, то ошибка в самом B. А что битов всегда хватает? Или просто завести ошибку LOWER_LEVEL_ERROR? На это, простите, можно только снисходительно улыбнуться
Так что ничего удивительного, что поклонники чистого С искренне верят, что abort "самое правильное решение", им больше не во что верить...
А потом я так понимаю "пользователи" твоей программы вынуждены фтыкать в корку? Тогда придется признать, что это никакие не пользователи, а такие же как ты разработчики, которым поневоле приходися участвовать в разработке твоей программы. А нормальных пользователей у твоих программ не бывает что ли?
Я, как правило, пишу просто
сode:--------------------------------------------------------------------------------
if (p == NULL) abort;
В случае чего можно abort заменить макросом, вставляющим строку и функцию. Будет не хуже синего экрана виндов.
какого фига программист разработал сигнатуру функции, которую не поддерживает возврат ошибок?Бывает такое, что возвращать ошибку некому.
Есть предусловие: abcp is a valid pointer. Кто не спрятался -- я не виноват.
Все проверки приводят только к разрешению написать хуёвый код. Обяхательно найдется пидорас, который воспользуется тем, что прога не будет вылетать в этой функции, но вылетит в другой.
Так было в винде 98, например, когда игра "Цивилизация-2" делала free, а потом писала в память что-то. С выпуском 2000 винды она перестала работать, и все наехали на Микрософт. В результате Микрософт из-за жалоб приняло решение встроить к код нечто: если имя бинаркника civ2.exe, то память освобожлать через жопу.
Все почему? Потому что когда-то в 98/95 винде было криво написана какая-то функция, и она что-то там делала не совсем так.
Кроме того, если программист начал прятать свои ошибки в одной функции, то ему придётся заниматься этим повсюду. Все вызовы, присваивания и разыменовывания обрастут многочисленными проверками самого себя, код раздуется.
> В таком случае однозначно второй, причём с ассертом, который будет компилиться и в релизе.
"Ассерт, который будет компилиться и в релизе" называется обработчиком ошибки.
Отличие заключается в первую очередь не в реализации (она как раз может не сильно
отличаться от ассерта а в смысле происходящего.
Грубо говоря, в сработавшем ассерте виноват программер, который его поставил,
так как он объ#$ался в предположениях относительно того, что происходит в его проге.
В замеченной им ошибке виноват кто-то еще.
Привычка некоторых программеров выполнять проверки ассертами не снимает с них
ответственности за происходящее, так как в том месте, где ассерт потенциально
может сработать, должен быть нормальный обработчик, который, если даже и не исправит
ситуацию, по крайней мере сможет сказать, что это невозможно.
конечно нет никакой разницы между внешними данными и аргументами функции,. т.к.
в общем случае, для отдельной функции/модуля нет никакой особенной самой программы, есть только внешний мир (разделенный на "зоны" с большей степенью доверия или меньшей) - особенно - это хорошо видно на больших программах/системах.
Современная программа - это конгломерат большего кол-ва разных модулей, написанного разными людьми в разное время на разных языках, исповедующими разные подходы, стили и т.д., имеющими разные ценности, цели ит .д..
Современная программа работает на очень разных компьтерах, системах и т.д.; контактирует с очень разным окружением, набором ресурсов и т.д.
Современная программа используется для решения очень разных задач очень разными пользователями (кто-то хочет решить свою прикладную задачу, а кто-то хочет повысить свои привилегии в системе и т.д.)
и как в любых системах - основные проблемы появляется не при написании/появлении первой версии, а при последующих изменениях, т.к. очень часто экономиться на полной проверке внесенных изменений, и проводятся проверки лишь O(1) сложности.
И как раз при таких изменениях - очень сильно начинают играть то, насколько каждый отдельный разработчик каждого отдельного модуля/функции при предыдущей разработке закладывался на то, что есть какая-то особенная отдельная программа - в которой все хорошо.
ps
Полная сложность проверки изменения - O(N где N-кол-во уже имеющей функциональности/кода, что выливается в O(N^2) для всей системы, поэтому на практике и стараются проводить проверки изменений только вида O(1)
На C# или Java я обычно вообще не пишу валидацию аргументов на null, поскольку это не очень то и нужно, если пользователю функции доступны исходные тексты. Он может по стректрейсу кликнув мышкой увидеть в какой строчке вылетел NullReferenceException. Если в строчке встречаются не только переменные-аргументы, то придется поставить брекпоинт и зайти под дебагом. В любом случае в IDE это делается всё быстро.
Мои пять копеек:
почитайте у Фаулера на сайте ( http://www.martinfowler.com/ ) статью Fail Fast. Весьма разумный текст, на сайте у очень уважаемого человека.
Так программы пишутся для программистов, или для пользователей?
Программы пишутся программистами для пользователей.
дык, вот в том-то и проблема, что Fast fail нужен только программистам, а не пользователям.
Потом поговорим, если захочется =)
Там программист Jim Shore пишет, что ему удобнее править Fail Fast-ошибки.
ну, и отлично. Но что из этого следует?
Еще раз спрашиваю - для чего пишутся программы?
для того, чтобы пользователи могли решать свои прикладные задачи?
или для того, чтобы программисты могли в программах быстро править ошибки?
Ошибки всегда будут, поэтому, если программист не позаботится о том, как ему быстро исправлять свои ошибки, это будет означать, что он не заботится о пользователях, для которых пишет программы. Плюс еще и доставит неудобство тем, кому, возможно, придется править его код.
можно исправить лишь очень малую часть ошибок.
зы
если правильных состояний в программе N,
то ошибочных 2^N.
Расскажи это Донульду Кнуту (TeX) и Дэну Бернштейну (qmail).
Ты готов поставить, например, 1000$ на то, что эти программы ведут себя корректно при нехватке памяти или диска?
Кнут, например платит деньги за обнаруженные ошибки в написанной им реализации TeX, за каждую последующую в 2 раза больше. Можешь денег заработать.
так ты не ответил на вопрос - ты готов поставить 1000$ на то, что эти программы корректно себя ведут при нехватке памяти или диска?
Вот они, думаю, готовы.
Особенно - это относится к qmail-у, как к программе взаимодействующей с внешней средой, и меньше к tex-у, т.к. tex - это простая batch-программа (или другими словами - tex - это большая функция, а не программа).
Для программиста - слова "программа работает" - означает, что если все хорошо (памяти и диска хватает, диск не отваливается, нет хардварных проблем, ресурсы ОС не выжраны) - то его программа отработает нормально - выдаст корректный результат.
Для пользователя же - слова "программа работает" - означает, что программа должна себя корректно вести - всегда, даже при прямом ядерном ударе, что не должны запарываться файлы на диске, если сбоит память,
что почта должна обрабатываться, даже если отвалился диск, что разбор остальной почты должен вестись, даже если один из челов умудрился прислать 8 гиговое письмо и т.д.
Покажите человека со средним достатком, который готов будет поставить штуку баксов на любую такую программу
Что человек регулярно ошибается при написании кода? Что часть этих ошибок пролезает через тесты в релиз?
Failing fast seems like it could resultВот уж действительно - программы для программистов, а не для пользователей. Что лучше для юзера - что прога работает медленно (используя значение по-умолчанию вместо отсутствующего параметра из конфиг-файла или что она просто вылетает без понятных (для пользователя, не для программиста) причин?
in pretty fragile software. Sure, it
makes defects easier to find, but what
about when you deploy the software
to customers? We don’t want the application
to crash just because there’s
a typo in a configuration file.
Мы говорили о fail fast.
Я и полагаем, что такая штука позволяет проще править баги -> в релизе этих багов будет меньше, так как просто их физически успеешь больше исправить.
Чем fail fast плох для пользователя, я не вижу. Почему? Да элементарно. Если где то произошло что-то, чего программа не ожидает, то рано или поздно это где-то напакостит, и программа свалится. Только свалится где-то далеко, и понять причину будет нельзя. Мало того, пока она будет валиться, ошибки могут нарастать снежным комом, а потом еще в конце и не дай бог сохранятся в БД.
Пользователь будет просто очень рад. Программа притворялась рабочей, а потом взяла и все одним махом затерла, и в довершение упала.
То есть чем раньше свалится обреченная программа, то, очевидно, тем меньше она успеет натворить.
Если уж тебе ну очень надо, чтобы программа не валилась как можно дольше (может быть ты там ракетой или луноходом управляешь ну убери ты ассерты из релиза, и всех делов.
Если где то произошло что-то, чего программа не ожидает, то рано или поздно это где-то напакостит, и программа свалится.Принципиально неверная позиция.
Вполне себе позиция. Не хуже других.
Failing fast seems like it could result in pretty fragile software. Sure, it makes defects easier to find, but what about when you deploy the software to customers? We don’t want the application to crash just because there’s a typo in a configuration file. One reaction to this fear is to disableТеперь по поводу твоих слов. Вылетает она не без понятных причин, а очень даже понятных. Очепятка в свойстве. Если пользователь умудрился допустить очепятку, правя это свойство, то он поймет эту причину.
assertions in the field. Don’t do that! Remember, an error that occurs at the customer’s site made it through your testing process. You’ll probably have trouble reproducing it. These errors are the hardest to find, and a well-placed assertion explaining the problem could save you days of effort.
On the other hand, a crash is never appropriate. Fortunately, there’s a middle ground. You can create a global exception handler to gracefully handle unexpected exceptions, such as assertions, and bring them to the developers’ attention. For example, a GUI-based program might display an unexpected problem has occured in an error dialog and provide an option to email tech support. A batch-processing system might page a system administrator and continue with the next transaction (see Figure 5 for an example). If you use a global exception handler, avoid catch-all exception handlers in the rest of your application. They’ll prevent exceptions from reaching your global handler. Also, when you use resources that have to be closed (such as files be sure to use finally blocks or using statements (in C#) to clean them up. This way, if an exception occurs, the application will be returned to a fresh, working state.
Если же причина таки польззователю непонятна - повторюсь еще раз. Игнорирование ошибки ни к чему хорошему не приведет. Программа свалится позже, но с СОВСЕМ непонятной ошибкой, ни программисту, ни пользователю. И на ее исправление могут уйти недели.
Если у меня сервер вдруг станет медленно работать из-за опечатки - я совершенно наверняка перерою пол системы, пока замечу мелкую очепятку в конфиг файле, и на это уйдут недели, и все эти недели я буду рвать на себе волосы.
Если где то появились неправильные данные, то кто-то это заметит. На что-то это повлияет.
Потому что если этого никто не заметит, и ни на что не повлияет - значит это данные, которые никому не нужны, и их можно спокойно выкинуть из программы и забыть.
Может быть у тебя эти неправильные данные сохранятся в БД, может быть эти данные потом кто то будет пытаться парсить, и не дай бог, нагенерит еще ошибок, или это были не данные, а ссылка на объект, и программа потом вылетит с null pointer exception, программисту или пользователю понять ГДЕ ИМЕННО сгенерилось неправильное значение, будет ОЧЕНЬ сложно.
Или ты надеешься, что, возможно, ошибку заметит потом какой то другой код в системе? И исправит ее, и пойдет дальше?
Может, конечно, быть и так, но в частности от этого и пытается предостеречь нас автор. Он говорит - проверяйте данные на ошибки в том месте кода, где эти данные генерятся. Тогда по stack trace'у ексепшена ты сможешь точно увидеть, в какой строчке кода у тебя сгенерились неправильные данные.
Если же данные будут проверяться на неправильность в противоположном месте системы, то понять, где же возникла ошибка, и какой же участок кода надо править будет очень сложно. Придется долго и нудно дебагиться, и еще не факт, что все получится.
А вообще, по-моему, вы видите в этом методе то, чего там нет. Ведь, по сути, автор утверждает - ставьте как можно больше проверок, тогда вам будет проще понять, где у вас ошибка. Истинность утверждения очевидна. Польза от этого тоже очевидна.
А валиться после ошибки, или нет - уже решение программистов. Автор про это говорит, и в моей "продленной" цитате это выделено жирным.
Что лучше для юзера - что прога работает медленно (используя значение по-умолчанию вместо отсутствующего параметра из конфиг-файла или что она просто вылетает без понятных (для пользователя, не для программиста) причин?Почему ты забываешь про третий вариант - вылететь с ошибкой "syntax error" ?
Даже если выбирать из двух предложенных, я предпочту второй. Пусть она лучше вообще не запускается, чем запускается и делает не то, что я от нее хочу.
Also, when you use resources that have to be closed (such as files be sure to use finally blocks or using statements (in C#) to clean them up.Кстати, в мейнстримовых языках (C++, Java, C#) от этих финализаторов не портится ли стек? То есть исключение, пойманное на верхнем уровне, не теряет дамп стека, не запорченный финализаторами?
Если б там портился стек, то, я думаю, программа свалилась бы после первого же return'a.
Теперь по поводу твоих слов. Вылетает она не без понятных причин, а очень даже понятных. Очепятка в свойстве. Если пользователь умудрился допустить очепятку, правя это свойство, то он поймет эту причину.Заметь, в примере не опечатки проверяются, а только присутствие парамера. Если я напишу MaxConnections={EQ, то прога этого не отловит.
Если же причина таки польззователю непонятна - повторюсь еще раз. Игнорирование ошибки ни к чему хорошему не приведет. Программа свалится позже, но с СОВСЕМ непонятной ошибкой, ни программисту, ни пользователю. И на ее исправление могут уйти недели.
Это, имхо, вполне нормально и удобно - использовать значения по-умолчанию при отсутствии параметров. И, поверьте, в этом случае отсутствие параметров ни к чему плохому не приведёт даже в отдалённом будущем. На то они и параметры по умолчанию, чтобы прога их корректно обрабатывала. Фраза - если ошибку не заметили, то она обязательно проявится потом - это ничем не подкреплённые абстракции. Я могу привести десятки контрпримеров. Я ничего не имею против failfast, просто не надо его совать всюду, куда лезет. В частности, валиться из-за отсутствия параметра в настроечном файле. У каждой техники есть своя область применения.
при обработке исключения неплохо иметь stack trace, на тот случай, если он понадобится при отладке
его можно брать либо с живого стека, который только что отмотали, либо при отмотке сохранять в надёжное место
для выполнения финализаторов тоже нужен стек, соответственно первый вариант отпадает
А то, что в примере что то недопроверяется - нашел к чему прикопаться. Это же пример.
По поводу ошибки, которая потом не проявилась - может быть один конструктивный вариант - эти данные потом никому не понадобились. Это скорее исключение, чем правило. Потому что, обычно, программы все таки делают что то полезное, что то, что кому то потом понадобится.
Если ты можешь привести еще какие то контрпримеры, встречающиеся в релаьном мире, я с удовольствием тебя выслушаю
И, думаю, снова не понял =)
Если при генерации эксепшена, перед поиском его обработчика, делается снимок стек трейса с живого стека, то с чего бы ему потом теряться куда то?
а куда класть снимок? он же может быть длиной в весь стек
Разве что то мешает?
вопрос в том, как на самом деле происходит?
StackTraceElement stackTrace[]
По поводу ошибки, которая потом не проявилась - может быть один конструктивный вариант - эти данные потом никому не понадобились.Смотря что ты понимаешь под ошибкой.
И что под ошибкой понимаешь ты? И контрпримеры с твоим пониманием ошибки?
ЗЫ Я не иронизирую, мне правда интересно.
Просто на это нужно навесить дополнительную функциональность, которая будет обеспечивать нормальную (с точки зрения пользователя) желательно контекстную реакцию на сбой в работе программы. Например, если операции, которые выполняет программа относительно самостоятеьные, то можно сохранить состояние программы после последней успешной операции (в первую очередь пользовательских данных при этом выдать пользователю соответсвующее сообщение и т.д (аля Ворд). Или в случае серверной программы записать в лог, и перезапустить сервис, возможно отключив модуль, который вызывает проблемы.
Похоже, что ты и (опять) не видите разницы между валидацией данных полученных извне, а аргументов функции. Аргументы фукнции нам даёт сама программа, а не кто-то извне. Они обязаны быть корректными, их не нужно проверять и исправлять.Такой подход подходит для монолитных программ.
Монолитные программы обладают рядом преимуществ:
* Возможность продуманного дизайна на всех уровнях.
* Возможность статической проверки разных аспектов корректности кода (например, статической типизации).
* Возможность не вставлять по этим причинам динамические проверки корректности, что позволяет добиться высокоэффективного кода.
К сожалению, возможности человека по построению сложных систем ограничены. И каждая ошибка в монолитной системе может разрушить её целиком. Поэтому наиболее сложные программные системы устроены в виде, как тут было сказано, конгломератов.
Например, если посмотреть на типичный сервер-чего-нибудь, там будет ядро ОС и куча процессов. Понравилось бы тебе, если бы при баге в одном из них в корку падали бы все, и сервер останавливался?
И это не связано с безопасностью: предположим, в корку падали бы все процессы от данного пользователя. А что, один "взбесившийся" процесс вполне имеет возможность нагадить в память всем, надо бы всех их остановить до выяснения. Но так не делают, а наоборот, вводят защиту памяти с динамическими проверками доступа, чтобы одному процессу было трудно случайно или специально нагадить другим.
Другой пример - работа с базами данных. Даже если с базой работает только твой код, то, наверное, ты всё равно проверяешь результат каждого SELECT'а на то, что он возвратил непустое множество там, где оно должно быть непустым и т.д. Существуют "сильно связанные" среды, где не нужно руками вставлять проверки, но значит, это делается незаметно где-то в недрах библиотеки.
Наоборот, база данных не умрёт, если клиентскому процессу вдруг придёт SIGSEGV, а вместо этого корректно закроет соединение и откатит транзакцию, и продолжит работать с другими клиентами. Даже если один человек писал и сервер, и клиента.
Эти требования отказоустойчивости не следует путать с сокрытием ошибок.
Сбойный модуль должен прекратить работу так, чтобы было легче понять, где ошибка. Важный этап после этого - реальное исправление ошибки. Иначе получается другой вид сокрытия ошибок - засирание логов/stderr неинформативными сообщениями, из которых непонятно, какие из них представляют реальные проблемы.
Например, с появлением Java вошли в моду программы, которые во время работы непрерывно срут многостраничными дампами стека. Соответственно, с развитием и усложнением программы всё сложнее отфильтровать что-то полезное оттуда. Нужно не только добавлять проверки и отладочный вывод, но и исправлять найденные проблемы и убирать безобидные сообщения.
> программа свалится. Только свалится где-то далеко, и понять причину будет нельзя. Мало того, пока она будет
> валиться, ошибки могут нарастать снежным комом, а потом еще в конце и не дай бог сохранятся в БД.
Слишком максималистская позиция.
Что лучше для пользователя - падать по Fast Fail раз в час? или по Slow Fail раз в год? тем более в прикладной программе, а не в серверном сервисе
> Если где то произошло что-то, чего программа не ожидает, то рано или поздно это где-то напакостит, и
> программа свалится.
Смотря как программы писать.
Есть код самовостанавливающийся (ошибки с течением времени нивелируются есть код, который саморазрушающий (ошибки с течением времени разрастаются).
И надо просто уметь писать код - самовостанавливающим, и не писать код - который саморазрушается.
Полностью моя позиция по поводу ошибок выглядит следующим образом - в случае ошибка программа должна сообщить об этом пользователю, но продолжать работать дальше, может быть даже хромая.
Такое поведение дает пользователю выбор - в случае ошибки иметь хотя бы частичный результат.
Пример - если в текстовом редакторе отказал показ картинок, в ряде случае - лучше чтобы редактор продолжал хромать дальше пусть даже с потерей этих картинок, чем не запускаясь совсем.
Подход Fast Fail - предлагают пользователю только два варианта - все или ничего.
когда ворд сохраняет документ так, что потом не может его прочесть, бывает обидно, наверное
хотя это совсем не серверный, эээ, сервис
а наверняка ведь потому, что когда-то раньше забыли проверку корректности вставить
Но если программа - не работает (закрывается сразу по Fast Fail-у то даже умный пользователь не сможет ничего сделать.
я считаю своих пользователей - умными.
хотя это совсем не серверный, эээ, сервис
смысл в том, что эту проблему легко обойти внешним образом - делать backup-и, пользоваться версионными системами хранения документов и т.д.
проблему - программа не работает, потому что считает, что в ней где-то ошибка - обойти внешним образом нельзя.
Если я напишу MaxConnections={EQ, то прога этого не отловит.Если бы я хотел, чтобы использовалось значение по умолчанию, я бы не стал писать явное значение в конфиг.
Это, имхо, вполне нормально и удобно - использовать значения по-умолчанию при отсутствии параметров.
Раз я его туда записал, значит, программа должна его обработать, и если не может, сказать об этом сразу и громко.
Игнорировать команды пользователя - как раз означает считать его глупым, а не умным.
Представь, что тебе каждый вечер прислуга приносит пиво (фантазии, ага).
А вот однажды ты с утра решил, что ночью будешь работать, и с утра же заказал к вечеру вместо пива кофе.
А слуга не расслышал, что именно ты хочешь.
Как лучше, если он сразу переспросит, и не уйдёт, пока не получит ответ, или же проигнорирует приказ, и вечером принесёт, как обычно, пива, поскольку это значение по умолчанию?
> пользоваться версионными системами хранения документов и т.д.
что-то мало кто из пользователей ворда так делает, наверное, это таки не очень легко
> проблему - программа не работает, потому что считает,
> что в ней где-то ошибка - обойти внешним образом нельзя.
неправда, можно обойти точно так же
не делать те действия, когда проявляется ошибка, вместо это взять бекап и попробовать другие действия
кроме того, если программа считает, что в ней ошибка, значит в ней ошибка
а теперь сравни - какой круг жизненных ситуаций больше - где нам важна каждая мелочь результата, а где важен только общий ход решения.
default-ные значения и хромание дальше - обычно обеспечивают общий ход решения, может быть жертвуя какими-то частностями.
> не делать те действия, когда проявляется ошибка, вместо это взять бекап и попробовать другие действия
Приведу даже плохой пример - промах по памяти.
Есть сложный документ - при открытии которого возникает промах по памяти.
По Fast Fail-у программа обнаруживая это - сразу выходит.
По Slow Fail-у программа информирует пользователя о промахе по памяти, но продолжает работать дальше.
В каком из случаев я все-таки смогу что-то поделать с документом, и добиться нужного мне результата?
Т.е. мне кажется правильным подход, где входные параметры функции проверяются на правильность, и в случае неправильных параметров немедленный выход из функции с информацией об ошибке (эксепшион, или что-то в этом роде). А дальше это уже дело более высоких уровней программы, где и что предпринять, чтобы разрешить проблему. Понятно, что убить приложение это самое простое решения для программиста.
Ты это про каких пользователей говоришь - про массового? про "глупого"? про "умного"?
Ты каких пользователей хочешь культивировать - умных или глупых?
Как Fast Fail позволяет умным пользователям чаще добиваться результата, чем глупым?
а что мешает самой программе бакапить?
а если попробуешь, получишь опять fault через несколько инструкций
а вот если декодер уже устроен модульным, и формат документа подходящий, то можно и перехватить ошибку, и пропустить непонятную часть
только вот у грамотных людей, которые заранее планируют такой дизайн, и "промахов по памяти" не будет (то есть если и будут, то сильно реже менее тривиальных проблем)
а вот запросто может быть такое при использовании недоверенных плагинов/библиотек; соотвественно грамотный разработчик подумает о защите памяти от таких плагинов
Допустим на этих картинках находится жизненно-необходимая для меня информация.
Тогда я все-таки предпочту, чтобы вывелись испорченные картинки, так как это мне поможет хоть как-то восстановить эту важную информацию.
> или внятные изобращение вместо испорченных картинок, которые сообщяют о проблемах,
Зачем "вместо"? что нам это дает? откуда такое желание противопоставить одно другому?
Я хочу чтобы было и то, и другое - чтобы были и испорченные картинки, и сообщение о том, что картинки возможно испорченные.
ну и опять перехватим.
помниться во времена win98-win2k - тот же Crash Guard очень хорошо помогал от таких проблем, позволяя многим программам, имеющим проблемы работы с памятью, работать нормально.
Особенно это было хорошо видно на игрушках.
> для меня информация.
Обычно, восстановление данных с повреждённого источника - отдельная операция, отличающаяся от нормального чтения, и алгоритмы используются другие. Так пользователь понимает, что дела идут не самым лучшим образом, и возможны проблемы с восстановлением.
Поэтому функция обычного чтения даёт сбой, и можно воспользоваться, смотря по ситуации, функцией продвинутого восстановления. В драйвер ФС поэтому не встраивают fsck, это отдельная программа для нештатных ситуаций.
Как быть - если меня устраивает результат - даже ошибочно работающего модуля? например, который по краям дает артефакты?
Зачем такой модуль должен быть отключен?
Просто мне кажется, не нужно мешать в кучу никоуровненые программерские техники, стиль программирования и т.д. вместе с функциональностью, которую ты хочешь от программы (не знаю, как ее назвать -- пусть "феил-саив поведение") -- это скорее относиться не к стилю программирования, а к подходам в дизайне приложения.
Я бы не хотел, чтобы жизненно важные данные обрабатывались программами, для которых необходимы такие костыли.
Я хочу знать, когда используется подобный костыль. Лучше всего - поставить его вручную, и тут же написать баг-репорт.
> Особенно это было хорошо видно на игрушках.
Игрушки, как я помню, никогда не отличались высоким качеством кода.
Это хорошо, что они бесплатно достаются, платить за такое деньги было бы обидно.
т.е. ты готов ждать, когда в программе будут исправлены все баги, и не готов работать с бета-версиями?
> и не готов работать с бета-версиями?
я готов работать с бета-версиями, и часто это делаю, именно поэтому я хочу знать, возникла ли проблема в моём случае, и если да, то какая, насколько серьёзная, как её исправить и т.д.
> Как быть - если меня устраивает результат - даже ошибочно работающего модуля?
Это значит, возможно осмысленное продолжение, даже если проверка показывает проблему.
Значит, это не error, а warning.
Вставить в программу опцию "continue-on-warnings" гораздо проще, чем собственно определить, где какие проверки делать.
Тебе же следует включить эту опцию, и радоваться артефактам в углах.
И что под ошибкой понимаешь ты?Ну отсутствие строчки в настроечном файле (и даже отсутствие самого файла) - это точно не ошибка. Это варнинг. А в примере пдфки (всё никак не запомню имя автора) эту ситуацию искусственно поднимают в ранг ошибок.
1. Каких задач больше - центральных (где важна каждая мелкая деталь решения) или периферийных (где важен только общий ход решения)?
2. Есть ли у человека/центрального модуля время/ресурсы на то, чтобы разбираться со всеми проблемами периферии?
3. Как Fail Fast позволяет пользователю лучше выполнить свою прикладную задачу? особенно в случае - если ошибка не может быть быстро исправлена?
4. На какой программе проще добиться нужного результата - на той, которая из-за Fail Fast-а выходит сразу, отключает сразу модуль, или на той - которая хромает дальше?
5. Каких пользователей должен в первую очередь поддерживать разработчик? Потребности каких пользователей разработчик должен удовлетворять в большей степени? "умных" или "глупых"?
6. как долго вы или пользователи готовы ждать выхода стабильной версии, на фоне того, что уже есть люди, которые вовсю работают с новыми глючными beta-версиями, но при этом уже получающими больший "результат"?
7. на основе каких данных разработчик может решить, что такое error или warning? почему это должен решать не пользователь?
Пару раз уже писал, что это не так.
Подход fail fast говорит только о том, что неправильные данные надо проверять в том месте кода, где они генерятся. Точка.
Что ты будешь делать с возникшим ексепшеном - твое сугубо личное дело. Тихо писать в лог, мылить на почту девелоперам, или пользователя нотифайить диалогбоксом - что угодно.
Программа не обязана валиться при любом чихе. Тебя видимо просто название метода обманывает.
1. Каких задач больше - центральных (где важна каждая мелкая деталь решения) или периферийных (где важен только общий ход решения)?А не важно, так как, если детали не важны - я бы предпочёл вообще о них не упоминать. А если я зачем-то о них думаю, значит они важны. Игнорировать моё мнение - со стороны компьютера - явное нарушение субординации.
. Есть ли у человека/центрального модуля время/ресурсы на то, чтобы разбираться со всеми проблемами периферии?Пример был, когда уже разобрались. Чувстуешь разницу?
в том-то и дело, что Fail Fast предлагает либо все, либо ничего.
> Подход fail fast говорит только о том, что неправильные данные надо проверять в том месте кода, где они генерятся. Точка.
Если произошел exception, значит остальная часть функции не выполнилась - значит не произошло хромания
программы дальше.
Возьмем для простоты чисто функциональный подход: есть функция - которой передаются данные, она возвращает результат.
Fast Fail говорит - если внутри такой функции произошла проблема, то функция должна вернуть exception.
т.е. по Fast Fail-у на уровне функции мы имеем - все - хороший результат или ничего - exception.
Но я как пользователь хочу иметь следующее: в случае ошибки - мне нужен и результат (пусть даже ошибочный) и сообщение/сообщения об ошибке.
Такая информация мне или программе - даст намного больше возможностей для принятия решения, чем голый exception.
какой результат ты хочешь получить от деления на 0, например?
Откуда появилась информация о том, что ты думаешь об этих деталях?
Вот есть программа/модуль - они что-то делают, у них возникли какие-то внутренние ошибки - откуда они знают что ты о них думаешь? они телепаты?
В примере - я написал строчку в конфиг, но ошибся в синтаксисе.
например, бесконечность.
даже если мы находимся в int-е, то MaxValue.
откуда взялась информация - что это ты написал эту строчку? и что эта строчка не была прописана инсталятором, взята вместе с другими с другого конфига, взята со старой версии, перестала работать в данном окружении и т.д.?
например, бесконечность.ты бы хотел, чтоб налог с тебя так посчитался?
даже если мы находимся в int-е, то MaxValue.
и что эта строчка не была прописана инсталятором, взята вместе с другими с другого конфига, взята со старой версии, перестала работать в данном окружении и т.д.?в этом случае я тоже хочу знать, что программа не справилась с проблемой самостоятельно и придётся разбираться; то есть я вообще не хочу таких случаев, но если уж возникли, то я хочу знать, что это не так, если проблема не обычная
неправильный синтаксис конфига - не обычная ситуация, и я хочу, чтобы так было подольше; зная, что такое программы, я не хочу, чтобы они решали за меня
если государство - жесткое формальное, то - нет.
если государство - самовосстанавливающееся от ошибок, то пофигу.
Откуда у тебя берется уверенность, что у тебя есть ресурсы на вникание в каждую мелочь?
когда тебе пришлют счёт на +Inf, это будет означать, что самовосстановления не произошло
разве ты бы не предпочёл, чтобы эту ошибку исправили без тебя, в налоговом отделе, и тебе бы не пришлось ходить с глупым счётом, и объяснять, что столько денег не бывает?
так вот нужно и на себя брать аналогичные обязательства - разбираться со своим софтом, а не рассчитывать, что после потери целостности, сути которой ты не понял, можно будет что-то восстановить
Зачем контролировать, например, при решение системы уравнений каждую выкладку? если проще проверить результат: или подставив его в начальное уравнение, или оценив примерный диапазон решения и т.д.?
Я не хочу вникать в каждую мелочь, я хочу, чтобы разработчик софта принял меры, которые позволят получить более качественный код. В тех же редких случаях, когда происходит сбой, я хочу узнать пораньше, и получить достаточно информации, чтобы оценить масштаб, последствия и т.п. Я не хочу, чтобы это делала программа непонятным ни мне, ни автору образом.
Я знаю, что искусственный интеллект не создан, и что не дело программ - принимать решения там, где это неспособен сделать человек.
> или оценив примерный диапазон решения и т.д.?
ASSERT именно это и делает
после чего сообщает, что результат бессмысленный
если пришлют, то - да, и как раз присылка такого счета и означает, что государство/налоговая - не самовостанавливающиеся.
т.к. при отсылке счета, можно легко впендюрить в налоговую модуль, который проверял бы счет на разумность.
И вот такой модуль - и является элементом самовостановления системы.
> который проверял бы счет на разумность.
дык, а я про что? разумная проверка в правильном месте - на границе модулей
> И вот такой модуль - и является элементом самовостановления системы.
А вот подстановка +Inf является элементом саморазрушения - модуль проверки мог бы и не просечь ошибочный счёт. Или ты бы предпочёл получить приблизительный счёт и не знать, что он составлен на основании какой-то незаконной лажи?
И запись в логе не поможет. Прикинь, официальное письмо: "мы на самом деле знаем, что счёт неверный, но ты всё равно заплати, это нужно для самовосстановления государства".
А что на самом деле нужно для восстановления - это модуль расчёта должен возвратить отказ, и записать в лог диагностику. Чтобы одни побежали исправлять баг, а другие - считать вручную.
ps
неформальные системы эффективнее, чем формальные,
но, конечно, неформальные системы требуют более сложную (более умную) управляющую подсистему.
Фантастика. Хотя бы просто, чтобы программисты задумывались, что в определенных местах программы могут произойти ошибки, и что можно в случае ошибки сделать. А не как многие, особенно в языках с поддержкой исключений, пишут для случая, когда все работате хорошо, иначе исключение, а там кто-то что-то с ним сделает наверно.
> Значит, это не error, а warning.
промах по памяти - это error или warning?
отсутствие прописанной опции - это error или warning?
неправильная настройка - это error или warning?
окружение не совпадает с тем, на которое расчитывала программа - это error или warning?
зы
после 99% ошибок - возможно осмысленное продолжение, и это и есть хромание дальше.
в типичном случае:
локально - error - процесс аварийно завершается
глобально - в системе, содержащей несколько процессов - может быть и error, и warning, и даже info
> отсутствие прописанной опции - это error или warning?
это как?
> неправильная настройка - это error или warning?
если программа умеет определять, что это неправильная настройка, значит она не такая уж неправильная, а вполне предусмотренная
> окружение не совпадает с тем, на которое расчитывала программа
аналогично
если логика программы распознала необычное окружение - значит, разработчик предусмотрел такое окружение
программная система - по определению формальная
> вполне предусмотренная
> аналогично
> если логика программы распознала необычное окружение - значит, разработчик предусмотрел такое окружение
напомню, что в реальности работает троичная логика (да, нет, не знаю а не двоичная.
соответственно даже формальный мир делится на 3 зоны (а не на две) - окружение, в котором программа сможет работать, окружение, в котором программа не сможет работать, и окружение - хз.
соответственно лишь две зоны из трех - являются предусмотренные разработчиком.
и если программа - поняла, что это не есть хорошее окружение, то из этого ничего не следует.
ps
также всегда остается вариант - что программа или разработчик неправильно определили, что такое "хорошее" окружение.
Доказать сможешь, что неформальную систему нельзя построить поверх формальной?
или даже, что нельзя формальную построить поверх неформальной?
программа не может этого понять
она либо поймёт, что "что-то не так, и неизвестно - что", либо найдёт конкретную неправильность окружения, возможность которой было предусмотрена заранее
ASSERT и аналоги как раз обычно используются для того, что бы вовремя заметить, что что-то не так, и не ясно, где проблема - в окружении или в коде
> Доказать сможешь, что неформальную систему нельзя построить поверх формальной?
тривиальная индукция
> тривиальная индукция
можешь доказать, что правомочен переход с n на n+1?
можешь доказать, что формальную систему со степенями свободы, например, 10^100 можно до сих пор рассматривать как формальную?
> например, 10^100 можно до сих пор рассматривать как формальную?
А ты напиши такую программу, а потом посмотрим, как её рассматривать.
Дык, это как раз к тебе вопрос - как ты собрался доказывать переход с N на N+1, если реальный мир - ограничен, в отличии - от мат. абстракций.
так же и формальные системы больше определенного размера можно лишь рассматривать, как неформальные, опять же из-за ограниченности наших возможностей.
Современные программы - уже давно превысили этот порог. (именно поэтому, например, так туго идет развитие параллельных языков - потому что там "подъемность" формализма заканчивается буквально на нескольких операторах, а с неформальными системами работать пока никто не умеет).
> А ты напиши такую программу, а потом посмотрим, как её рассматривать.
Ну, а систему c 10^41 состояний - можно рассматривать как формальную?
ps
Современный компьютер = Состояние винта*состояние памяти*кол-во внешних входов*кол-во состояний за 10 лет = 10^12 * 10^9 * 10^3 * 10^17 = 10^41
так же и формальные системы больше определенного размера можно лишь рассматривать, как неформальные, опять же из-за ограниченности наших возможностей.Применяя различные способы работы со сложностью, например, модульность и иерархию. Что даёт возможность найти проблему рядом с местом её проявления.
Потому что другие способы не работают: нельзя рассчитывать, что после воззваний к совести и ответственности глючащей программы, или скажем вследствие угрозы наказания или обещания вознаграждения, она заработает.
Счёт на +Inf не поможет тебе решить проблему с неправильным подсчётом налогов, а контролируемый отказ модуля подсчёта - поможет.
> а с неформальными системами работать пока никто не умеет
Как ты думаешь, пользователи хотят программы, с которыми можно работать, или с которыми работать никто не умеет?
Современный компьютер = Состояние винта*состояние памяти*кол-во внешних входов*кол-во состояний за 10 лет = 10^12 * 10^9 * 10^3 * 10^17 = 10^41Выдыхай немедленно! Я пожалуй сделаю паузу, пока тебя не попустит.
так ты можешь показать, что всегда возможна правомочная свертка этих 10^41 состояний до сильно меньшего числа состояний?
> Потому что другие способы не работают: нельзя рассчитывать, что после воззваний к совести и ответственности глючащей программы, или скажем вследствие угрозы наказания или обещания вознаграждения, она заработает.
И какое - это отношение имеет к формальным/неформальным системам?
ты путаешь теплое с мягким.
модульность и иерархичность - могут быть как формальными, так и неформальными.
также и воззвания к совести - могут быть как неформальными, так и формальными.
выбор на самом деле сейчас следующий:
формальные программы - с которыми уже(из-за их неподъемности) не умеют работать,
неформальные программы - с которыми еще не умеют работать.
Причем по первому варианту - никаких прорывов в ближайщее время не предвидеться.
и даже простейший модуль - типа того же Layouting-а - на формальных правилах - не запишешь.
зы
и свертка больших формальных систем к удобоваримому кол-ву состояний - приводит нас к необходимости работать с неформальными системами.
и даже простейший модуль - типа того же Layouting-а - на формальных правилах - не запишешьгде нельзя придумать формальные правила, туда и assert не вставишь, соответственно наш разговор не про такие случаи
мы обсуждаем те случаи, когда возможна формальная проверка каких-то предположений
например, если layout manager подписался сделать все элементы видимыми и доступными, увеличив при необходимости размер окна, то это условие вполне может быть проверено формально
если хитроумный алгоритм не справился с этой задачей, то я хочу, чтобы он выдал достаточную для баг-репорта диагностику, и отказался от работы, а модуль верхнего уровня вызвал бы более простой и надёжный алгоритм
если вместо этого элементы продолжают наваливаться друг на друга, как ни в чём не бывало, я недоволен
тут под рукой реальный пример программы, которая не справляется с такой задачей независимо от размера окна, мне даже не видно, что за кнопки там внизу, их какая-то лажа закрывает; а на другой машине работает; куда копать, не понятно
дык, речь же идет не о проверках (пусть даже формальных а о принятии решений - на основе этих проверок.
> если хитроумный алгоритм не справился с этой задачей, то я хочу, чтобы он выдал достаточную для баг-репорта диагностику, и отказался от работы, а модуль верхнего уровня вызвал бы более простой и надёжный алгоритм
начем основывается уверенность, что механизм вот такого принятия решения можно сделать формальным?
я правильно понимаю, что если он выведет текст шрифтом размера 3 пиксела или 300 пикселей тебе тоже не понравиться?
или выведя элементы, количеством больше 100, без какого-либо видимого упорядочивания?
или шрифтом, который отсутствует на компьютере?
или выведя текст с межстрочным и межбуквенным интервалом в 1000 пикселей или 0 пикселей?
или белым по белому?
или бледнозеленым по зеленому?
и т.д.
>> например, 10^100 можно до сих пор рассматривать как формальную?
> А ты напиши такую программу, а потом посмотрим, как её рассматривать.
Вообще говоря, крупные конфиги имеют обычно более 100 явно настраиваемых параметра (то есть степеней свободы каждый из которых (в среднем) может принимать более 10 значений. То есть системы с таким числом степеней свободы вполне реальны, даже если не сводить компьютер к конечному автомату.
почитайте оба, что такое степень свободы
я правильно понимаю, что если он выведет текст шрифтом размера 3 пиксела или 300 пикселей тебе тоже не понравиться?да, я не рад таким делам, поэтому не люблю программы, использующие техники сокрытия ошибок, мешающие справляться с подобными проблемами
или выведя элементы, количеством больше 100, без какого-либо видимого упорядочивания?
или шрифтом, который отсутствует на компьютере?
или выведя текст с межстрочным и межбуквенным интервалом в 1000 пикселей или 0 пикселей?
или белым по белому?
или бледнозеленым по зеленому?
можешь показать почему, например, горизонтальную координату нельзя представлять в виде двух степеней свободы: x1, x2 , где x = x1 + x2 * 1000?
а систему с N бинарными ячейками в виде системы со степенями свободы N-штук?
Применяя различные способы работы со сложностью, например, модульность и иерархию. Что даёт возможность найти проблему рядом с местом её проявления.К сожалению, далеко не всегда поможет, так как далеко не все ошибки отлавливаемы подобным образом вообще (например, нельзя отловить, если мы какую-ту величину в сложном случае дважды учли. Зато навредить - может, особенно с учётом того, что реальных формальных правил (подобно правилам учёта налогов) обычно крайне мало по сравнению с объёмом программы.
Потому что другие способы не работают: нельзя рассчитывать, что после воззваний к совести и ответственности глючащей программы, или скажем вследствие угрозы наказания или обещания вознаграждения, она заработает.
Счёт на +Inf не поможет тебе решить проблему с неправильным подсчётом налогов, а контролируемый отказ модуля подсчёта - поможет.
Мне эти "быстрые провалы" следующее напоминают: допустим обрабатывается налоговая декларация, которую человек заполняет и отсылает (или отдаёт в окошко). Поле "адрес проживания" является, естественно, обязательным, и контролировать его заполнение нужно. Теперь о том, как выглядит fail fast в таком случае. Человек отсылает декларацию с адресом "xxx д 13 кв 666". Ему её возвращают (по почте, или в окошке) со словами "ошибка адреса - сокращения 'дом' и 'квартира' должны завершаться точной". Дальнейшая обработка не ведётся, а из окошка, когда человек просит "ну проверьте, дальше хоть всё верно заполнено", ему отвечают "декларация заполнена неправильно, ошибка вот - перезаполните, будем проверять дальше".
ты так и не ответил на более важный вопрос:
на основе чего ты считаешь, что у тебя есть ресурсы, чтобы справиться с этими проблемами лично?
Дальнейшая обработка не ведётся, а из окошка, когда человек просит "ну проверьте, дальше хоть всё верно заполнено", ему отвечают "декларация заполнена неправильно, ошибка вот - перезаполните, будем проверять дальше".Если модули проверки разных строчек независимы, то можно проверять дальше. Хорошая процедура проверки в таком случае покажет все ошибки в заполнении и ответит отказом.
Процедура, скрывающая ошибки, вместо этого возьмёт такую декларацию на обработку, а через несколько месяцев ты узнаешь, что должен заплатить штраф, так как не подал вовремя правильно заполненную декларацию.
А что такое степень свободы? И как это применить к IT и программам в частности?
почитайте оба, что такое степень свободы
> чтобы справиться с этими проблемами лично?
где я сказал, что так считаю?
А вот спроси у DG. Он применяет, и даже их число за 10 лет оценивает
постоянно, прося выдавать все проблемы на уровень пользователя, а также подчеркивая, что все проблемы этот пользователь сможет решить, и что на это у него есть ресурсы.
Чуваки, я с вас фигею.
Вы что обсуждаете вообще? Процедура формальной проверки корректности программы эквивалентна этой программе. Точка нах.
Можно проверять корректность не полностью, а только некоторые инварианты, которые позволяют себя описать достаточно просто, так чтобы вероятность ошибки в описаниях инвариантов была достаточно мала. Чо вы вообще считаете?
---
Дай угадаю - ты распечатал текст по ссылке и его скурил? Чуваааак, его читать нужно было.
Какое нах отношение имеет ошибка при вводе адреса в декларации к внутренней ошибке программы?
Да, остальные спорщики, кажется, тоже дружно пропустили в том текстике мега-абзац, который здесь уже цитировал Алепар, про то, что ловить эксепшены можно и нужно, в таком случае стабильность проги только увеличивается, главное - внимательно подумать, где эти эксепшены ловить, и что делать при поимке (то есть какое именно действие считать неудавшимся).
Что лучше для пользователя - падать по Fast Fail раз в час? или по Slow Fail раз в год? тем более в прикладной программе, а не в серверном сервисеЛучше падать по Fail Fast сразу же после включения глючной функциональности, а не через 10 часов, когда я буду спать.
постоянно, прося выдавать все проблемы на уровень пользователя, а также подчеркивая, что все проблемы этот пользователь сможет решить, и что на это у него есть ресурсы.практика показывает, что это проще, чем "хромать"
напоминаю, что все ошибки исправить невозможноэто полная чушь, кстати
можно исправить лишь очень малую часть ошибок.
для каждого конкретного пользователя можно исправить все или почти все ошибки, на которые натыкается конкретно он
в хороших проектах так и происходит
для всех сразу пользователей тоже можно исправить почти все ошибки, в стадии feature freeze
к проектам, использующим принцип сокрытия ошибок, это не отностится - там со временем количество ошибок, на которые натыкаются пользователи, как правило, растёт со временем
Разумеется, говорить юзеру правду проще, чём его обманывать.
Если я правильно понял позицию дг, то он хочет зашибать бабло с юзеров,
создавая у них впечатление, что всё работает нормально (ms-way нах).
Моя цель - решать задачи пользователей, как следствие - пользователи почему-то начинают платить деньги за это.
> Если я правильно понял позицию дг, то он хочет зашибать бабло с юзеров,
> создавая у них впечатление, что всё работает нормально (ms-way нах).
не надо мне приписывать чужих позиций.
где я говорил, что надо обманывать пользователей?
где обман в позиции - сообщи о проблеме наверх, но попытайся получить хоть какой-то результат даже при наличии этой проблемы?
моя позиция - программа, в идеале, должна быть самодостаточной и не зависеть от пользователя, в том числе, и при появлении ошибок.
да, такие программы - на данный момент мало кто умеет писать, поэтому сегодняшние попытки такое сделать - получаются не очень, но...
ps
самодостаточность программ делается для эффективности
потому что наука - управление - говорит следующее:
1. эффективная масштабируемая система - это такая система, в котором нет сильного замыкания на центральный элемент
2. правильное (эффективное) поведение - периферийного или нижнего узла - в случае проблемы, это сообщить о проблеме наверх, попытаться исправить проблему своими силами
Сегодняшние же программы постоянно замыкаются на пользователя - и вот такое поведение очень и очень не удобно
две роли сейчас выделю особо:
1. Инструмент
2. Агент
"инструмент" - это программы, которые являются продолжением пользователя, увеличивая его возможности - такие программы можно сравнить с рукой, молотком, очками, гидроусилителем и т.д.
"Агент" - это программы, которые работают независимо от пользователя, обладают своей логикой и т.д.
Существенная разница между программой-инструментом и программой-агентом следующее:инструмент все принятия решений делегирует на уровень пользователя, агент принимает решения самостоятельно (указания пользователя скорее являются рекомендациями).
Основное отличие в применении следующее:
если пользователь эксперт в какой-либо области - ему удобнее работать с программами-инструментами, т.к. пользователь в этой области может и готов принять решение
если же область является периферийной для пользователя, где пользователь не может и не готов принимать решение - то удобнее работать с программами-агентами.
например, я не являюсь профессионалом в области железа, ПО системного уровня, дизайна, музыки и т.д. - и в этих областях мне удобнее работать с программами-агентами, которым я описываю, что я примерно хочу получить, а далее уже сами программы формируют решение.
Оставить комментарий
sergey_m
Представим себе эдакую большую программу, в которой десятки модулей и тысячи разных функций. Вот два начала одной и той же абстрактной функции. Какое вам больше нравится?