10.5 Надежность программирования
Рассмотрим вопросы надежности функционального программирования. Полезно
ошибки выполнения программы разделить на два класса.
• Класс A: ошибки, приводящие к немедленному прерыванию работы программы. При-
мерами таких ошибок является деление на ноль или доступ по неправильному адресу.
• Класс B: ошибки, не вызывающие немедленного прекращения работы программы. К
таким ошибкам относятся выход за пределы массива или незамеченная неправильная
адресация.
Языки программирования можно разделить на следующие два класса.
• Типизированные языки (языки с контролем типов). Язык является типизирован-
ным, если существует система типов для него, независимо от того присутствуют дей-
ствительно или нет типы в синтаксисе программы. Языки с контролем типов являются
явно типизированные, если типы есть часть синтаксиса, и неявно типизированные в
противном случае. Полностью неявно типизированные языки являются редкостью, но
такие языки как Haskell и Clean поддерживает написание больших программных фраг-
ментов с опущенной информацией о типах; система типов в этих языках автоматиче-
ски выводит тип для таких программных фрагментах.
• Нетипизированные языки. Языки, в которых не ограничены множества значений пе-
ременных, является нетипизированными: они не имеют типов, или, эквивалентно,
имеют один универсальный тип, которому принадлежат все используемые величины.
В этих языках операции могут применяться к неподходящим аргументам: результат
может иметь вполне определенное значение или операция может оканчиваться неуда-
чей или приводить к непредсказуемым последствиям. Чистое ламбда–исчисление яв-
ляется предельным случаем нетипизированных языков: в нем единственная операция –
аппликация и она всегда успешна, поскольку любая величина есть функция.
Программный фрагмент называется надежным (или безопасным), если он при
своем выполнении не приводит к ошибке класса B. Языки, в которых все программные
фрагменты надежны, называются надежными языками. Поэтому надежные языки исклю-
чают большинство коварных, незаметно появляющихся ошибок.
• Нетипизированные языки могут быть надежными за счет проверок во время выполне-
ния.
• Типизированные языки могут быть надежными, если до выполнения отвергаются все
потенциально ненадежные программы. Кроме того, в этих языках может присутство-
вать проверка во время работы программы. Главная цель системы типов языка – обес-
печение надежности языка за счет исключения всех ошибок класса B.
Большинство нетипизированных языков есть, по необходимости, полностью на-
дежными (например, Лисп). Иначе программирование в отсутствии проверок во времени
компиляции и во времени работы программы приводило бы к весьма ненадежным про-
граммам. Ассемблер принадлежит к неприятной категории нетипизированных ненадеж-
ных языков.
Надежность – несколько примеров
Типизированные Нетипизированные
Надежные
Haskell, Clean Lisp
Ненадежные
C Assembler
Как правило, отсутствие надежности в разработке программ мотивируют временем
исполнения кода. Проверки времени выполнения, необходимые для того, чтобы сделать
программу безопасной, дорого стоят. Надежность требует стоимостных затрат даже в
языках с интенсивным статическим анализом: тестирование выхода за пределы массива
невозможно полностью сделать во время компиляции.
81