пятница, 25 июня 2010 г.

[prog] В завершение темы об ошибках в программе, unit-тестах и системах типов

Созрел до заключительного поста в поднятой несколькими заметками (первая и вторая) ранее теме.

Ошибки в программах – это плохо. Даже если они не досаждают пользователям и не отваживают клиентов от производителей ПО, все равно ошибки обходятся дорого. Главным образом за счет времени и ресурсов, которые направляются на их обнаружение и исправление. Замечу, что на обнаружение и исправление, а не на предупреждение. Поскольку наиболее распространенные способы обеспечения качества ПО (читай: различные формы тестирования) обеспечивают, в лучшем случае, хороший отлов ошибок. Уже внесенных в ПО ошибок.

Более выгодно было бы иметь средства предупреждения ошибок. Тогда и тестировать нужно было бы меньше.

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

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

Но, если формализованные и заматематизированные методы программирования не пройдут, то что же останется?

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

  • строгая типизация;
  • статическая типизация;
  • модульность и инкапсуляция;
  • исключения;
  • сборка мусора и отсутствие адресной арифметики;
  • статически-типизированные шаблоны и генерики (в таких языках как Ada, C++, Eiffel, Java, D, C#, Scala);
  • void safety в языке Eiffel;
  • паттерн-матчинг, который приходит в мейнстрим благодаря Scala, OCaml и Haskell;
  • иммутабельность данных, на которой делается акцент в OCaml, Haskell, D. В зачаточном виде привнесена в мейнстрим C++ным const-ом;

Это, я бы сказал, крупные, очень заметные изменения. А есть и менее заметные, очень обыденные, но не менее эффективные. Например, запрещение присваиваний внутри оператора if. Или появление в Java специального оператора for. Мелочи, но изрядный объем неприятных ошибок они устранили как класс.

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

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

  • ошибки по недомыслию. Не додумались разработчики, что старый код нельзя использовать в новых условиях – Ариан 5 взорвался на старте;
  • ошибки по незнанию. Не знали программисты одного отдела, что программный модуль, разработанный в другом отделе, будет выдавать координаты в другой системе счисления – потерялся марсианский спутник;
  • ошибки по невнимательности. Забыл программист при выделении буфера добавить один байтик для завершающего ноль символа и…

Так вот, все о чем я говорил выше касается только ошибок по невнимательности. Языки программирования, к счастью, становятся все более и более дуракоустойчивыми bulletproof-естыми. Что есть хорошо, ибо чем меньше возможности разработчику допустить случайную, глупую ошибку – тем лучше.

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

Отправить комментарий