Возможно ли достичь абсолютного нулевого состояния ошибки для крупномасштабного программного обеспечения?


71

Я говорю о 20-30+ миллионах строк кода, программного обеспечения в масштабе и сложности Autodesk Maya, например.

Если вы заморозите разработку до тех пор, пока это необходимо, сможете ли вы на самом деле исправить все ошибки до тех пор, пока просто не будет ни одной ошибки, если такая вещь может быть проверена компьютерами? Каковы аргументы за и против существования системы без ошибок?

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

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


11
«Мне сказали несколько ведущих программистов» - они мне не кажутся лучшими программистами. Они звучат как лучшие хакеры. Одна из первостепенных обязанностей программиста заключается в том, чтобы понять, что делает их код и как он влияет на систему в целом. Вот почему у нас есть TDD, шаблоны проектирования и т. Д. Если это невозможно, система является ненужной - процесс разработки был выполнен хаотичным, случайным, недисциплинированным, ненаучным способом.
вектор

51
Если вы еще не знаете, что ошибка существует, это все еще ошибка?
Blrfl

5
@Blrf: более важно, если конечный пользователь не знает, есть ли ошибка, существует ли она?
Mattnz

40
«Есть два способа конструирования программного обеспечения. Один из способов - сделать это настолько простым, чтобы не было никаких недостатков. И другой способ - сделать это настолько сложным, чтобы не было явных недостатков ». - CAR Hoare
Эндрю Льюис

5
Это так, но многие люди не хотят ставить под сомнение их фундаментальные убеждения.
Джоан Венге

Ответы:


92

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

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

Перво-наперво - вы игнорируете общую картину того, как работает ваша программа. Он не работает изолированно на идеальной системе. Даже самые простые из программ «Hello World» работают в операционной системе, и поэтому даже самые простые программы подвержены ошибкам, которые могут существовать в операционной системе.

Наличие библиотек делает это более сложным. В то время как операционные системы имеют тенденцию быть достаточно стабильными, когда дело доходит до стабильности, библиотеки представляют собой смешанный пакет. Некоторые прекрасны. Другие ... не так много ... Если вы хотите, чтобы ваш код был на 100% свободен от ошибок, то вам также необходимо убедиться, что каждая библиотека, с которой вы работаете, полностью свободна от ошибок, и во многих случаях это просто невозможно у вас может не быть исходного кода.

Тогда есть темы для размышления. Большинство крупномасштабных программ используют потоки повсюду. Мы стараемся быть осторожными и писать потоки таким образом, чтобы не возникали условия гонки и взаимоблокировки, но просто невозможно протестировать каждую возможную комбинацию кода. Для того, чтобы проверить это эффективно, вам необходимо изучить все возможные последовательности команд, проходящих через ЦП. Я не делал математику по этому вопросу, но подозреваю, что перечислить все возможные игры в шахматы было бы проще.

Дела идут от трудного к невозможному, когда мы смотрим на саму машину. Процессоры не идеальны. Оперативная память не идеальна. Жесткие диски не идеальны. Ни один из компонентов внутри машины не разработан так, чтобы быть идеальным - он достаточно «хорош». Даже идеальная программа в конечном итоге потерпит неудачу из-за сбоя в работе машины. Вы ничего не можете сделать, чтобы остановить это.

Итог: можете ли вы написать «Ошибка свободного программного обеспечения»?

НЕТ

Любой, кто говорит тебе иначе, не имеет понятия.

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


РЕДАКТИРОВАТЬ: Некоторые люди отметили замечательный момент, который я полностью упустил из виду: компилятор.

Если вы не пишете в ассемблере, вполне возможно, что компилятор испортит ваш код (даже если вы докажете, что ваш код "идеален").

Список ошибок в GCC, одном из наиболее часто используемых компиляторов: http://gcc.gnu.org/bugzilla/buglist.cgi?product=gcc&component=c%2B%2B&resolution=---


8
Ответ по-прежнему «нет», потому что всегда будут «ошибки», когда что-то работает - совсем не так, как хотелось бы клиенту или владельцу продукта. Некоторые из нас могут вызывать эти запросы функций или запросы на изменение поведения или добавление функциональности, но для человека, которого каждый день раздражает какая-то «ошибка», вещь, которая их раздражает, является ошибкой. (Это долгий способ сказать, что некоторые ошибки находятся в глазах смотрящего.) БЕСПЛАТНЫЙ КОД БАГОВ невозможен. Стремитесь к коду, который достаточно хорош, чтобы соответствовать своему назначению.
fast_now

6
Я сделаю еще один шаг: код может иметь скрытые дефекты, например, у вас может быть код, который неправильно проверяет входные данные. Если по какой-то счастливой причине входные данные никогда не выходят за пределы диапазона, ошибка никогда не проявляется. Затем, однажды во время технического обслуживания или изменения функций, этот фрагмент кода вызывается откуда-то еще, и иногда он использует его со значением вне диапазона. Ошибка теперь проявляет себя - но она была там все время. Вы можете иметь степень безумия во всем этом - но устранение любой возможности неправоты все еще невозможно.
fast_now

11
@ JohnR.Strohm Я не уверен, почему вы думаете, что программа «модулятор потока сообщений», программа с 556 строками кода, имеет какое-то отношение к вопросу о теоретической системе из 20 миллионов строк. За исключением, может быть, демонстрации того, как трудно было доказать правильность крошечной программы, было бы астрономически труднее доказать правильность массивной программы.
Эрик Кинг,

9
Хотя первоначальный вопрос этого не сделал, я хотел бы отметить, что существует огромная разница между «теоретически возможным» и «практически возможным». Хотя кодовая база из 20 миллионов строк без ошибок, возможно, теоретически возможна, на современном рынке это почти наверняка практически невозможно. Кто знает, что ждет в будущем.
Эрик Кинг,

4
@ JohnR.Strohm Вы должны прочитать статью более внимательно. Они говорят сами: It is important to note, however, that even all of these steps provide no guarantee of absolute security. It is tempting to believe that a formally specified and proved program should be absolutely correct, but there are several reasons why a proved program may not behave exactly as expected.- значит, нельзя доказать, что они не содержат ошибок, а, скорее всего, имеют меньше ошибок. Скорее как TDD.
Изката

27

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

Практически говоря, в системе того размера и объема, о которой вы говорите, это НЕВОЗМОЖНО . Для написания такой системы без ошибок и написания системы, доказывающей, что это займет экспоненциально больше времени, может потребоваться 1000 лет: вам придется придумывать все возможные варианты использования и писать систему, которая будет тестировать каждую из них. один - и я не верю, что есть способ определить, что вы действительно охватили каждый вариант использования в системе того размера и области, о которой вы говорите, во всем, что напоминает разумное количество времени.

IMO, ваш вопрос немного неверно направлен: наша цель как разработчиков - не писать «безошибочное» программное обеспечение. Наша цель - написать ПОЛЕЗНОЕ, ГИБКОЕ, ЛЕГКО ОБЕСПЕЧЕННОЕ ПО.

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

Ремонтопригодность: ошибки могут быть легко изолированы и исправлены, и НЕ создавать новых ошибок.

Гибкость: ваша система легко изменяется и расширяется без значительного перепроектирования и простоев: для большинства изменений требуется просто добавить новый класс или модуль, который будет соответствовать уже хорошо разработанным шаблонам и инфраструктуре.

Хорошие методы проектирования, хорошие методы управления, хорошая командная работа, добросовестные разработчики - вот формула ХОРОШЕГО ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ . (не идеально, но хорошо )


3
«Доказательство этого МОЖЕТ также быть математически возможным, путем разработки тестовой системы, которая будет выполнять каждую строку кода всеми возможными способами - всеми возможными вариантами использования». Такой программы вообще не существует (и это можно доказать!). Так что общего алгоритма доказательства правильности не существует.
Джорджио

3
Исправление: Достигнуто безошибочное программное обеспечение, ПОЛНОЕ С ФОРМАЛЬНЫМ МАТЕМАТИЧЕСКИМ ДОКАЗАТЕЛЬСТВОМ ПРАВИЛЬНОСТИ. Это было сделано в 1982 году. Google "модулятор потока сообщений".
Джон Р. Штром

6
@ JohnR.Strohm: не правда. Вот только одна цитата - есть несколько статей и несколько мест, в которых они затрагивают аналогичные проблемы: «Часто возникает вопрос:« Вы проверили верификатор? »Возможно, что удивительно, этот метаматематический вопрос часто задают инженеры, а не просто заостренный руководитель академики. Конечно, если машина когда-нибудь ответит на вопрос «Вы когда-нибудь лжете?», ответ будет не более информативным, чем когда человек отвечает на вопрос ».
Вектор

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

1
@ Джорджио - так что, IMO, следование передовым методам проектирования гораздо важнее, чем забота о себе с математической корректностью: разработайте свой код, чтобы он был хорошо интегрирован и совместим с тем, что уже есть, - и достаточно устойчив, чтобы легко обрабатывать дефекты, когда они выйти на свет (что они будут).
вектор

27

Согласно этой статье, встроенное программное обеспечение для космического корабля «Шаттл» подошло очень близко - в последних трех версиях программы на 420 000 строк была только одна ошибка в каждой. Программное обеспечение поддерживалось группой из 260 мужчин и женщин. Большое количество этих людей были проверяющими, единственной целью которых было найти ошибки.

Обновление программного обеспечения, позволяющее шаттлу осуществлять навигацию с помощью спутников глобального позиционирования, затронуло всего 1,5% программы, или 6 366 строк кода. Спецификации для этого изменения составили 2500 страниц. Спецификации для всей программы занимали 30 томов и занимали 40000 страниц, или в среднем десять строк кода на страницу спецификации.

Бюджет не был проблемой - при 35 миллионах долларов в год они могли позволить себе делать все правильно.


25
Одна обнаруженная ошибка каждый. Кто знает, сколько необнаруженных ошибок? :)
Андрес Ф.

8
Эта «одна ошибка» была особым случаем. Шаттл был изначально разработан и определено программное обеспечение для двух роботов. «Ошибка» заключалась в том, что там был еще код для поддержки второй руки.
Джон Р. Штром

4
+1 Пробежал без ошибок за 135 миссий с 1981 по 2011
MarkJ

5
@MarkJ: мы, вероятно, не знали бы, если бы у космического челнока действительно не было ошибок. Каждые миссии космического челнока постоянно, под пристальным наблюдением сотен людей, и любые ошибки в кодировании были бы исправлены / переопределены вручную.
Ли Райан

2
@LieRyan Который хорошо показывает одно замечательное свойство надежных систем - если они не дают катастрофических сбоев и всегда допускают ручную настройку, вы можете вместо этого использовать избыточные системы (например, в центре управления) для выполнения работы. Конечно, это имеет смысл, только если у вас есть такие избыточные системы, и если вы действительно можете гарантировать правильность и согласованность. В типичном бизнес-приложении сбой часто предпочтительнее работы в несовместимом состоянии - это разница между раздражением и, скажем, отправкой денег не тому парню. Или получать деньги без их отправки ...
Луана

15

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

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

Сколько ошибок мы можем ожидать от огромной программы? Одно число, которое я нашел, было «10 дефектов на 1000 строк» ​​(Code Complete 2-е издание, стр. 517 - просто использовался пример, без цитирования каких-либо данных), что дает нам от 200 000 до 300 000 ошибок в вашем программном обеспечении. К счастью, у нас есть способы улучшить качество программы. Модульное тестирование, обзоры кода и обычное ручное тестирование, как известно, уменьшают количество ошибок. Тем не менее, число все еще будет высоким.

Если бы мы могли решить 95% всех ошибок, это было бы невероятно. И все же у нас все еще будет от 10 000 до 15 000 ошибок в программном обеспечении.

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

Вы также, похоже, ошибочно полагаете, что если программное обеспечение не изменится, новых ошибок не появится. Если программное обеспечение зависит от сторонних библиотек, новые версии могут нарушать некоторые функции, что приводит к появлению новых ошибок, даже если код приложения остается прежним. Новые операционные системы могут также сломать приложение, которое ранее работало идеально (см. Популярный пример в Windows Vista). Учитывайте также ошибки компилятора и т. Д.

Неясно, могут ли инструменты для проверки кода действительно решить проблему с ошибками программного обеспечения. Конечно, невозможно решить проблему остановки для любой программы, но можно доказать, что программа ведет себя так, как указано ... Но что тогда? Возможно, в программе проверки есть ошибка. Может быть, в самой спецификации есть ошибка.

Ясно, что мы можем значительно сократить количество ошибок, но вряд ли мы когда-нибудь доберемся до нуля.

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

(выделение добавлено)

Ты прав. Это утверждение неверно. Вот пример:

int main() {
    int x[10];
    x[10] = 8; //Buffer overflow here
    return 0;
}

Теперь давайте исправим эту ошибку:

int main() {
    int x[11];
    x[10] = 8; //No buffer overflow here
    return 0;
}

Видеть? Мы исправили ошибку и не представили новых.

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

Допустим, что на каждые 100 ошибок, которые я исправляю, я случайно ввожу новую. Поэтому, если я исправлю 10 000 ошибок, я добавлю 100 новых ошибок. И если я исправлю эти новые ошибки, я внесу одну ошибку. Ну и что? В программе теперь на 9 999 ошибок меньше, так что, вероятно, это лучше, чем было (при условии, что новая ошибка не в 10 000 раз хуже, чем предыдущие).

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

Я был старым из нескольких ведущих программистов, что лучше не исправлять много ошибок из-за понятия, которое я упомянул в ОП.

Такое поведение небрежно. Если есть ошибка, и вы можете ее исправить. Сделай это. Конечно, вы должны сделать все возможное, чтобы предотвратить добавление новых, но если я добавлю одну маленькую ошибку на каждые 10 серьезных ошибок, которые я исправлю, это не является веской причиной, чтобы прекратить исправлять ошибки. На самом деле, это хорошая причина, чтобы продолжать исправлять ошибки .

Чем меньше ошибок вы исправите, тем меньше ошибок будет возвращаться вам в будущем

Чем меньше ошибок вы исправляете, тем больше ошибок останется в вашем программном обеспечении, раздражая ваших пользователей. Действительно, они не будут «возвращаться к вам в будущем». Они не вернутся, потому что они никогда не уходили. Понятие «вернуться» связано с регрессией. Опять же, можно снизить риск регрессий.

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

Менталитет « исправь ошибку, сделай ошибку» может быть связан с That Horrible Monster - кодом, который настолько нечитаем и не поддерживается, что простое прикосновение к нему порождает ошибки. Если в вашей кодовой базе есть монстр, вам может понадобиться сначала удалить его из монстра, прежде чем что-либо делать.

Наконец, если вы ужасный программист, есть риск, что все, к чему вы прикасаетесь, создает новые ошибки. Это, очевидно, заставит старших программистов нервничать. Тем не менее, говоря: «Не делай ничего. Не трогай ничего. Даже не дышите». Вероятно, это не правильный способ создать здоровую рабочую среду. Образование лучше.

Заключение:

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

+1: я сам искал пример бинарного поиска, был побежден;) Если бы 20 строк широко обсуждаемого и распространенного кода содержали ошибку в течение 20 лет, сколько времени вам понадобилось бы для 20-миллионной строки кода, которая в на какие самые десятки занятых людей когда-либо будут смотреть?
scrwtp

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

1
@JoanVenge Я привел этот пример, чтобы показать, как можно найти хитрые ошибки. В этом случае вставка копий была на самом деле правильной вещью, поскольку она оказалась правильной, а реализация, написанная с нуля, скорее всего, будет иметь больше ошибок. Инструменты и методы, которые мы - как отрасль в целом - используем, безусловно, не оптимальны. Лучшие практики легко игнорировать, а вредные привычки легко сохранить. В конечном счете, ошибки будут существовать всегда, потому что люди не совершенны. Но мы можем уменьшить количество ошибок, делая все возможное и настаивая на высококачественном образовании.
luiscubal

7
Я думаю, что ошибка в двоичном коде поиска демонстрирует, насколько сложен этот вопрос. Основной ошибкой в ​​поиске было потенциальное целочисленное переполнение в дополнении. Такие «ошибки» вездесущи, потому что большинство людей полагаются на неявное (и иногда ошибочное) предположение, что входные данные не будут достаточно большими, чтобы вызвать переполнение. Это действительно ошибка или просто плохо документированный интерфейсный контракт? Когда последний раз, когда вы ранжировали, проверяли слагаемые в целочисленном сложении или проверяли переполнение после факта?
Чарльз Грант

4
Ваши примеры серверов, чтобы подчеркнуть довольно очевидное наблюдение о языке программирования и качестве инструмента. Компилятор производственного качества для надежного языка должен был отказаться от компиляции вашего первого примера, вместо этого вернув фатальную ошибку компиляции. То, что даже ВОЗМОЖНО скомпилировать такую ​​мерзость, говорит вам обо всем, что вам нужно знать о качестве этих инструментов и возможности их использования для доставки безошибочного программного обеспечения.
Джон Р. Штром

12

Причины не написание программ безглючности в основном экономичные.

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

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

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

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

Проблема, напротив, заключается в следующем:

Хотя теоретически можно написать программу без ошибок, это будет очень дорого . Написание кода с доказательством его правильности сложнее, чем просто бросить что-то в стену и посмотреть, не заклеит ли она. Даже если «видеть, если он залипает» делается с помощью модульных тестов; и многие программисты даже не удосужились это сделать. Большинство программистов даже не знают, как это сделать, а это значит, что в качестве компании вам придется нанимать более дорогих.

Учитывая все затраты, типичный клиент более доволен дешевым программным обеспечением, которое работает хорошо в 99% случаев (и 99,9% времени после установки дополнительных обновлений), чем, возможно, в тысячу раз дороже программного обеспечения, которое хорошо работает в 100% случаев. время. Кроме того, клиент хочет иметь это программное обеспечение сейчас , а не через десять или двадцать лет.

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

Если вы заморозите разработку до тех пор, пока это необходимо, сможете ли вы на самом деле исправить все ошибки до тех пор, пока просто не будет ни одной ошибки, если такая вещь может быть проверена компьютерами?

Математически говоря, вы могли бы. С экономической точки зрения, зачем кому-то это делать? Это означало бы потратить двадцать лет и несколько миллионов долларов. Между тем, клиенты будут хотеть новые функции, а ваши замороженные приложения не смогут их предоставить. Поэтому, когда ваша идеальная версия готова, рынок уже занят вашими конкурентами.

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


Спасибо, хотя я хотел бы, чтобы большинство программ работало в 99% случаев, большинство крупных, которые я использую, как в OP, очень глючные. Но я думаю, что монополия и покупка конкурентов также учитывают это. Но я понимаю вашу точку зрения.
Джоан Венге

1
«Дорогой» относительно. Сравните стоимость поиска и исправления ошибок со стоимостью, например, радиотерапевтического аппарата, убившего нескольких пациентов и нанесшего увечья нескольким другим. (Google "Therac 25".)
Джон Р. Штром

6

Нет.

Дэвид Гилберт предложил свою вторую проблему математики еще в 1900 году, которая по сути попросила мир доказать, что арифметика работает так, как задумано. Позже он propsed « на проблему разрешения », который просил что - то подобное в логических терминах. « Первая теорема о неполноте » Курта-Геделя доказала в 1931 году, что никакая теория элементарной арифметики не может быть последовательной и полной. Представление Аланом Тьюрингом проблемы Entscheidungs ​​как « проблема остановки » переместило проблему прямо в суть этого вопроса, где он доказал, что невозможно доказать, будет ли программа работать до конца или нет. Учитывая, что неразрешимостьТакже невозможно доказать, есть ли в программе какие-либо ошибки или нет.

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


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

+1 за цитирование соответствующего теоретического фона. Я еще не знал, что «Entscheidungsproblem» называется на английском языке так же, как на немецком!
Peopleware

5
Согласитесь с Даниэлем. Задача о единственном случае; проблема остановки связана со всеми возможными случаями. Тривиально int main() { return 0; } останавливается и не содержит ошибок.
MSalters

1
Проблема остановки не говорит о том, что невозможно доказать, будет ли программа работать до конца; это говорит о том, что существуют программы, которые невозможно доказать. Обычные ежедневные программы не в этом классе. «Хотя доказательство Тьюринга показывает, что не может быть общего метода или алгоритма для определения того, останавливаются ли алгоритмы, отдельные экземпляры этой проблемы вполне могут быть подвержены атаке. Учитывая конкретный алгоритм, часто можно показать, что он должен остановиться для любого входа, и фактически ученые-компьютерщики часто делают это как часть доказательства правильности ».
Эндолит

6

Errare humanum est

Даже если вы пишете код на формальном языке, таком как B-метод , который вы можете использовать для математического доказательства соответствия требованиям,

Даже если вы используете формальный язык спецификации,

Всегда есть человеческий шаг, заключающийся в извлечении потребностей пользователя из одного или нескольких мозгов на компьютер.

Этот человеческий шаг подвержен ошибкам, и червь в яблоке.


1
Это все еще ошибка, когда программа выполняет то, что было задано, а не то, что предполагалось?
MSalters

Я думаю, что это ..
Джоан Венге

4
@MSalters - Конечно, это так. Не с контрактной точки зрения, но, в конце концов, заказчик не решил свою проблему. Вы бы полетели на самолете, компьютеры которого делают то, что спрашивали, но не то, что предполагали?
Mouviciel

3

Достаточная доля «ошибок», с которыми я столкнулся, может быть более правильно описана как несоответствие между дизайном системы и ожиданиями клиентов.

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

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

Короче говоря:

Нет.


+1 Разработчик и клиент могут иметь совершенно разные взгляды на то, что определяет «ошибка».
GrandmasterB

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

2

Если у вас достаточно жесткая и ограниченная спецификация, вы можете доказать безошибочную программу, но только на основе недоказуемых предположений о правильном функционировании всего остального в системе. Это означает, что невозможно доказать, что спецификации будут считаться правильными тем, кто поставил исходную проблему, или тем, кто использовал службу.


1

Я нашел раздел Джима Шора No Bugs очень полезным чтением на эту тему. Краткая форма: невозможно разрабатывать без ошибок, но мы можем работать таким образом, чтобы обнаруживать их как можно раньше.

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

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


1

О проверке компьютерной частью.

Есть два способа проверить программу с помощью компьютера. Один - тестирование, другой - использование системы доказательства.

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

Чтобы использовать систему проверки, вы начинаете с формальных требований (и они сами могут иметь ошибку, надеюсь, язык, используемый для требований, будет более подходящим, чтобы убедить себя, что в этом нет ошибки, чем с языком программирования), и конструировать / проверять с помощью помощь систем доказательства, что программа не содержит ошибок (и в системах доказательств есть вопрос об ошибках, но они оказались правильными). Современное состояние - это компилятор для подмножества C (и подмножество не является академическим, «CompCert поддерживает все подмножества MISRA-C 2004 C, а также многие функции, исключенные MISRA»).


Цитирую Дональда Кнута (из памяти): Вы можете доказать, что в программе нет ошибок, но это не значит, что в ней нет ошибок :-)
gnasher729

1

Нет, потому что компьютерная и программная среда, в которой работает приложение, будет продолжать меняться, даже если код заморожен. Операционная система продолжает развиваться с исправлениями и исправлениями, а также с устройствами и драйверами. Как только вы думаете, что достигли точки, в которой нет известных ошибок, AMD или nVidia выпустят обновление видеодрайвера, которое повлияет на ваше взаимодействие с видеоподсистемой. Теперь ваше приложение имеет визуальные дефекты (такие как мигание, мерцание или уменьшение частоты кадров) для клиентов, у которых есть определенная видеокарта или конфигурация (SLI? LOL).

Помимо аппаратного обеспечения и операционной системы, есть также несколько промежуточных программных продуктов под наиболее значимыми приложениями, которые также будут развиваться вне вашего контроля, и как только вы приведете свой код к нулевому дефекту, укажите уровни, под которыми вы получаете EOL.

Технология развивается, так же как и бизнес, использующий эту технологию, и идея «освобождения» кода невозможна или неосуществима. Бизнес, запрашивающий новый набор функций, не будет хорошо реагировать на то, что «у нас заблокирован код, пока мы преследуем все известные ошибки, и никто не сообщает о действительном дефекте программного обеспечения за X месяцев». Даже если бизнес купит эту линию, через X месяцев они спросят, как появляются новые функции, и ответ не может быть: «Мы решили продлить действие запрета, потому что Oracle просто выпустит патч, и нам нужно еще X месяцев чтобы подтвердить это ".

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


0

Да, но вы никогда не узнаете наверняка. Чем сложнее ты выглядишь, тем больше найдешь. Чем тяжелее используется система и чем больше крайних случаев, тем более вероятно, что вы обнаружите еще одно несоответствие с первоначальным намерением или спецификацией. Это подразумевает, что ошибка сама по себе не является точной вещью и часто будет зависеть от интерпретации, от того, насколько плохо некоторые оценивают воспринимаемую аномалию.

Это нечеткая вещь. Мало систем указано до последнего бита. Если система работает хорошо, и у пользователей нет претензий (они ничем не подвержены ошибкам), и они полностью адаптированы к ней, вы можете также назвать ее свободной от ошибок.


-2

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

Но, делая это, вы, как правило, не ставите себе задачу построить систему на 20 MLOC. Если написание кода без ошибок не является вашей целью, ни одна из них не должна создавать систему MLOC.

Мои собственные рассуждения таковы:

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

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

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

Это имеет следующие последствия в отношении вашего вопроса:

  • Учитывая, что в программном обеспечении есть ошибка, вы вообще ее исправите? Вам нужен программист, чтобы исправить ошибку, и программист будет стоить денег. Программист не может решить, стоит ли тратить деньги на это. Это роль человека, занимающего бюджет.
  • Могу ли я создать программное обеспечение 20MLOC с нуля, не оставляя в конце нефиксированных ошибок? Что ж, для создания 20MLOC потребовалось потратить огромные деньги. Это финансово глупо. И он не построен за один день. Но программное обеспечение для сегодняшних нужд, а не завтра. Будет предпринята ошибочная попытка распараллелить разработку , наняв множество программистов. Но тогда, скорее всего, вы не получите общую культуру, и появятся ошибки, будут потрачены впустую и задержки, и деньги закончатся, чтобы их исправить. Я не видел ни одной системы без ошибок такого размера. (Я видел системы без ошибок и системы 20MLOC, но они не были одинаковыми)
  • Я отвечаю за поддержку системы 20MLOC, которую я не писал. Смогу ли я достичь нуля известных ошибок? Это не зависит от программистов. Они не могут решить исправить ошибки, потому что это не их деньги на линии. Достаточно ли ROI, чтобы исправить оставшиеся ошибки? Что ж, система существует уже некоторое время, и пользователи привыкли к ней и используют ее причуды в своих повседневных делах. Если вы исправляете ошибки по принципу, человеку, у которого есть деньги, возможно, придется заплатить, чтобы перестроить неуказанную функцию, которая исчезла из системы, что стоило еще больше денег.

Все дело в деньгах, и это правильно.


-2

Да.

Но, как вы знаете, это требует слишком много усилий, чтобы того стоить.

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

  • Ошибка - это поведение, противоречащее спецификации.
  • Однако сбои в спецификации (например, 0-й закон робототехники) не считаются программными ошибками.
  • Дополнительные функции не считаются ошибками, если это не запрещено спецификацией.
  • Ради аргумента, противоречия в спецификации также не считаются программными ошибками.

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

"Но ждать!" Я слышу ваш протест: «Что если неожиданное (но, тем не менее, правильное) поведение одного модуля вызывает ошибку в другом?» Тогда ошибка находится во втором модуле. Модули без ошибок могут рассматриваться как API, а API, как вы знаете, требуют некоторого внимания для правильного использования.

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

«Но дай мне место, чтобы встать, и я переверну мир». - Архимед


Это требует усилий, но это окупается.
Лоран LA RIZZA

1
Если вы исключите ошибки спецификации из уравнения, все ваше программное обеспечение станет бесполезным: спецификации являются лишь инструментами, позволяющими записывать потребности пользователей относительно формальным образом, но в конце концов, удовлетворять нужно пользователя, а не спецификации. И создание спецификации - такая же часть разработки программного обеспечения, как и написание кода. В конце концов, полная формальная спецификация будет описывать поведение системы так же, как и финальный код, спецификация просто неэффективно выполняется.
Cmaster
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.