Созрел до заключительного поста в поднятой несколькими заметками (первая и вторая) ранее теме.
Ошибки в программах – это плохо. Даже если они не досаждают пользователям и не отваживают клиентов от производителей ПО, все равно ошибки обходятся дорого. Главным образом за счет времени и ресурсов, которые направляются на их обнаружение и исправление. Замечу, что на обнаружение и исправление, а не на предупреждение. Поскольку наиболее распространенные способы обеспечения качества ПО (читай: различные формы тестирования) обеспечивают, в лучшем случае, хороший отлов ошибок. Уже внесенных в ПО ошибок.
Более выгодно было бы иметь средства предупреждения ошибок. Тогда и тестировать нужно было бы меньше.
И тут на арену вырываются отдельные яркие представители того или иного экзотического направления в программировании. В последнее время это функциональщики, размахивающие флагами систем типов; сравнивающие программирование с доказательством теорем; объясняющих, что в отсутствии побочных эффектов однажды написанный фрагмент кода будет оставаться корректным… И обещающие другие благодати их славной, но воинствующей религии :)
Не буду пытаться оспорить эти тезисы. Пусть даже все это так и есть. На мой взгляд, если всем этим заветам следовать, то программирование должно превратиться в математическую дисциплину. Что невозможно, поскольку программирование – это не математика. Именно поэтому огромный объем полезного и успешно работающего кода ежедневно и ежечасно пишут люди вообще не имеющие математического образования.
Но, если формализованные и заматематизированные методы программирования не пройдут, то что же останется?
А останется плавная эволюция языков программирования. При которой языки программирования будут обрастать средствами, препятствующими возникновению ошибок. Эту эволюцию мы и так можем наблюдать на примере мейнстримовых языков:
- строгая типизация;
- статическая типизация;
- модульность и инкапсуляция;
- исключения;
- сборка мусора и отсутствие адресной арифметики;
- статически-типизированные шаблоны и генерики (в таких языках как Ada, C++, Eiffel, Java, D, C#, Scala);
- void safety в языке Eiffel;
- паттерн-матчинг, который приходит в мейнстрим благодаря Scala, OCaml и Haskell;
- иммутабельность данных, на которой делается акцент в OCaml, Haskell, D. В зачаточном виде привнесена в мейнстрим C++ным const-ом;
Это, я бы сказал, крупные, очень заметные изменения. А есть и менее заметные, очень обыденные, но не менее эффективные. Например, запрещение присваиваний внутри оператора if. Или появление в Java специального оператора for. Мелочи, но изрядный объем неприятных ошибок они устранили как класс.
Я думаю, что в дальнейшем мейнстримовые языки программирования будут вбирать в себя разнообразные техники из различных более-менее маргинальных языков. Каждое новшество (которое может быть совсем не новшеством в своем исходном языке) будет бороться с каким-то определенным классом ошибок. И так, потихоньку, шаг за шагом, разработчики языков будут лишать программистов возможности совершать хорошо известные нам сейчас ошибки (например, присваивание вместо сравнения в операторе if). Наверняка при этом будут возникать какие-то новые типы ошибок, сейчас неведомые.
Подчеркну, что я говорил только об очень узком классе ошибок. Можно разбить причины возникновения ошибок на три класса:
- ошибки по недомыслию. Не додумались разработчики, что старый код нельзя использовать в новых условиях – Ариан 5 взорвался на старте;
- ошибки по незнанию. Не знали программисты одного отдела, что программный модуль, разработанный в другом отделе, будет выдавать координаты в другой системе счисления – потерялся марсианский спутник;
- ошибки по невнимательности. Забыл программист при выделении буфера добавить один байтик для завершающего ноль символа и…
Так вот, все о чем я говорил выше касается только ошибок по невнимательности. Языки программирования, к счастью, становятся все более и более дуракоустойчивыми bulletproof-естыми. Что есть хорошо, ибо чем меньше возможности разработчику допустить случайную, глупую ошибку – тем лучше.
Но вот в чем я сильно сомневаюсь, так это в появлении языков программирования, которые способны защищать от двух первых классов ошибок (которые по недомыслию и по незнанию).