Внимание: выбор языка прикладного программирования является одним из основных идеологических вопросов в сообществе Internet/Unix. Люди сильно привязываются к данным средствам и иногда защищают их вопреки здравому смыслу. Если глава достигнет своей цели, то вполне может оскорбить фанатичных приверженцев всех языков, однако все остальные разработчики почерпнут из нее немало полезного.
14.2. Доводы против С
С — естественный язык операционной системы Unix. С начала 1980-х годов он стал доминировать в системном программировании почти повсеместно в компьютерной индустрии. За пределами сокращающейся ниши Fortran в научных и инженерных вычислениях, а также исключая невидимую массу финансовых приложений на языке COBOL в банках и страховых компаниях, С и его потомок С++ уже более десяти лет доминируют в прикладном программировании.
Поэтому утверждение о том, что С и С++ почти всегда являются неподходящим связующим материалом для начала разработки новых приложений, может показаться неверным. Тем не менее, оно справедливо. С и С++ оптимизируют машинную эффективность ценой увеличения времени реализации и (особенно) отладки. Несмотря на то, что писать на С или С++ системные программы и чувствительные ко времени выполнения ядра приложений все еще имеет смысл, мир значительно изменился со времен возвышения этих языков в 1980-х годах. Сегодня процессоры в тысячи раз быстрее, модули памяти в тысячи раз больше, а диски в
Падение цен фундаментально изменило экономику программирования. В большинстве обстоятельств уже не имеет смысла так экономить аппаратные ресурсы, как это позволяет С. Напротив, экономически оптимальный выбор состоит в минимизации времени отладки и максимизации возможности долгосрочного сопровождения кода. Следовательно, большинство видов реализации (включая создание прототипов приложений) лучше обслуживаются более новым поколением интерпретируемых языков и языков сценариев. Эта трансформация точно соответствует тем условиям, которые на предыдущем витке исторической спирали привели к восхождению C/C++ и снизили важность программирования на ассемблере.
Центральной проблемой С и С++ является то, что они требуют от программистов самостоятельно осуществлять управление памятью — объявлять переменные, явно управлять связными списками, определять размеры буферов, обнаруживать или предотвращать переполнение буферов, а также распределять и высвобождать динамическую память. Некоторые из указанных задач могут быть автоматизированы путем искусственных действий, таких как дополнение С программой сборки мусора, например, реализация Boehm-Weiser, однако конструкция С такова, что подобное решение не может быть совершенным.
Управление памятью в С — серьезный источник трудностей и ошибок. По оценкам одного исследования (цитата из [9]), 30 или 40% времени разработки отводится на управление памятью в программах, которые манипулируют сложными структурами данных. В это число даже не включаются затраты на отладку. Несмотря на отсутствие точных данных, многие опытные программисты уверены, что ошибки управления памятью являются единственным крупнейшим источником постоянных ошибок в реальном коде[119]. Переполнение буфера является обычной причиной аварий и брешей в системе безопасности. Управление динамической памятью особенно чревато порождением коварных и трудно отслеживаемых ошибок, таких как утечки памяти и проблемы недействительного указателя.
Вместе с тем не так давно ручное управление памятью имело смысл. Однако теперь "малых систем" больше нет, а в передовом программировании приложений ручное управление памятью не требуется. В современных условиях гораздо более целесообразно использовать язык реализации, который автоматизирует управление памятью (и на порядок сокращает количество ошибок ценой использования несколько большего числа циклов и памяти).
В недавней статье [63] собран впечатляющий массив статистических данных в пользу заявления, которое опытные программисты сочтут весьма правдоподобным: продуктивность программистов при работе с языками сценариев почти в два раза больше продуктивности при работе с С или С++. Данное утверждение хорошо согласуется с приведенной выше оценкой затрат времени (30-40%), а ведь еще следует учесть издержки отладки. Потери производительности при использовании какого-либо языка сценариев очень часто незначительны для реальных программ, поскольку такие программы склонны ограничиваться ожиданием I/O-событий, сетевой задержки и заполнением кэша, а не эффективностью, с которой они используют сам процессор.
В действительности, сообщество Unix медленно приближается к данной точке зрения, особенно с 1990 года, это видно по возрастающей популярности Perl и других языков сценариев. Однако развитие практики еще (к середине 2003 года) не привело к крупномасштабным переменам. Многие Unix-программисты до сих пор осмысливают урок, преподаваемый языками Perl и Python.