Шрифт:
Интервал:
Закладка:
Частично причиной того, что данные языки можно объединить в группу "языков сценариев" является то, что все они имеют почти совершенно идентичный онтогенез. Наличие динамической среды для интерпретации также сравнительно облегчает автоматизацию управления динамической памятью. Автоматизация управления динамической памятью требует использования ссылок (трудных для понимания адресов памяти, которые разработчик не в состоянии вычислять) вместо распространения копий значений или явных указателей. Использование ссылок делает динамический полиморфизм и ОО-методики следующим простым этапом.
Для того чтобы эффективно применять философию Unix, инструментарий программиста должен включать в себя не только С. Программисту потребуется изучить использование некоторых других языков в Unix (особенно языков сценариев), а также способы удобного сочетания нескольких языков, каждый из которых играет особую роль в крупных программных системах.
В данной главе рассматривается язык С и его наиболее важные альтернативы, обсуждаются их сильные и слабые стороны, а также виды задач, которым они наилучшим образом соответствуют. Ниже описываются языки С, С++, shell, Perl, Tcl, Python, Java и Emacs Lisp. Каждый обзорный раздел включает в себя учебные примеры приложений, написанных с использованием данных языков, а также ссылки на другие примеры и учебные материалы. Высококачественные реализации всех данных языков доступны в Internet в виде открытого исходного кода.
Внимание: выбор языка прикладного программирования является одним из основных идеологических вопросов в сообществе Internet/Unix. Люди сильно привязываются к данным средствам и иногда защищают их вопреки здравому смыслу. Если глава достигнет своей цели, то вполне может оскорбить фанатичных приверженцев всех языков, однако все остальные разработчики почерпнут из нее немало полезного.
14.2. Доводы против С
С — естественный язык операционной системы Unix. С начала 1980-х годов он стал доминировать в системном программировании почти повсеместно в компьютерной индустрии. За пределами сокращающейся ниши Fortran в научных и инженерных вычислениях, а также исключая невидимую массу финансовых приложений на языке COBOL в банках и страховых компаниях, С и его потомок С++ уже более десяти лет доминируют в прикладном программировании.
Поэтому утверждение о том, что С и С++ почти всегда являются неподходящим связующим материалом для начала разработки новых приложений, может показаться неверным. Тем не менее, оно справедливо. С и С++ оптимизируют машинную эффективность ценой увеличения времени реализации и (особенно) отладки. Несмотря на то, что писать на С или С++ системные программы и чувствительные ко времени выполнения ядра приложений все еще имеет смысл, мир значительно изменился со времен возвышения этих языков в 1980-х годах. Сегодня процессоры в тысячи раз быстрее, модули памяти в тысячи раз больше, а диски в десять тысяч раз больше, причем примерно по тем же ценам[118].
Падение цен фундаментально изменило экономику программирования. В большинстве обстоятельств уже не имеет смысла так экономить аппаратные ресурсы, как это позволяет С. Напротив, экономически оптимальный выбор состоит в минимизации времени отладки и максимизации возможности долгосрочного сопровождения кода. Следовательно, большинство видов реализации (включая создание прототипов приложений) лучше обслуживаются более новым поколением интерпретируемых языков и языков сценариев. Эта трансформация точно соответствует тем условиям, которые на предыдущем витке исторической спирали привели к восхождению C/C++ и снизили важность программирования на ассемблере.
Центральной проблемой С и С++ является то, что они требуют от программистов самостоятельно осуществлять управление памятью — объявлять переменные, явно управлять связными списками, определять размеры буферов, обнаруживать или предотвращать переполнение буферов, а также распределять и высвобождать динамическую память. Некоторые из указанных задач могут быть автоматизированы путем искусственных действий, таких как дополнение С программой сборки мусора, например, реализация Boehm-Weiser, однако конструкция С такова, что подобное решение не может быть совершенным.
Управление памятью в С — серьезный источник трудностей и ошибок. По оценкам одного исследования (цитата из [9]), 30 или 40% времени разработки отводится на управление памятью в программах, которые манипулируют сложными структурами данных. В это число даже не включаются затраты на отладку. Несмотря на отсутствие точных данных, многие опытные программисты уверены, что ошибки управления памятью являются единственным крупнейшим источником постоянных ошибок в реальном коде[119]. Переполнение буфера является обычной причиной аварий и брешей в системе безопасности. Управление динамической памятью особенно чревато порождением коварных и трудно отслеживаемых ошибок, таких как утечки памяти и проблемы недействительного указателя.
Вместе с тем не так давно ручное управление памятью имело смысл. Однако теперь "малых систем" больше нет, а в передовом программировании приложений ручное управление памятью не требуется. В современных условиях гораздо более целесообразно использовать язык реализации, который автоматизирует управление памятью (и на порядок сокращает количество ошибок ценой использования несколько большего числа циклов и памяти).
В недавней статье [63] собран впечатляющий массив статистических данных в пользу заявления, которое опытные программисты сочтут весьма правдоподобным: продуктивность программистов при работе с языками сценариев почти в два раза больше продуктивности при работе с С или С++. Данное утверждение хорошо согласуется с приведенной выше оценкой затрат времени (30-40%), а ведь еще следует учесть издержки отладки. Потери производительности при использовании какого-либо языка сценариев очень часто незначительны для реальных программ, поскольку такие программы склонны ограничиваться ожиданием I/O-событий, сетевой задержки и заполнением кэша, а не эффективностью, с которой они используют сам процессор.
В действительности, сообщество Unix медленно приближается к данной точке зрения, особенно с 1990 года, это видно по возрастающей популярности Perl и других языков сценариев. Однако развитие практики еще (к середине 2003 года) не привело к крупномасштабным переменам. Многие Unix-программисты до сих пор осмысливают урок, преподаваемый языками Perl и Python.
Та же тенденция, хотя и выраженная не так ярко, наблюдается за пределами мира Unix, например, в продолжающемся переходе от С++ к Visual BASIC, который заметно проявляется в разработке приложений для Microsoft Windows и NT, а также в движении к Java в мире мэйнфреймов.
Аргументы против С и С++ в равной степени применимы к другим традиционным компилируемым языкам, таким как Pascal, Algol, PL/I, FORTRAN и компилируемые диалекты BASIC. Несмотря на отдельные "героические усилия", такие как Ada, отличия между традиционными языками остаются внешними при сопоставлении их основных конструктивных решений, оставляющих управление памятью программисту. В Unix большинство из когда-либо созданных языков доступны в виде высококачественных реализаций с открытым исходным кодом. Несмотря на это, в широком использовании в Unix или Windows не осталось других традиционных языков. Разработчики отказались от них в пользу С или С++. Соответственно, в данной главе они не рассматриваются.
14.3. Интерпретируемые языки и смешанные стратегии
Языки с автоматическим управлением памятью осуществляют его с помощью диспетчера памяти, встроенного в их динамически исполняемые модули. Как правило, среды выполнения в таких языках разделены на программную часть (собственно выполняющийся сценарий) и часть интерпретатора с управляемой им динамической памятью. В Unix-системах (а также в других современных операционных системах) память интерпретатора может совместно использоваться несколькими программными частями, что сокращает фактические издержки для каждой из них.
Использование сценариев — нисколько не новая идея в мире Unix. В 1970-х годах, в эпоху гораздо меньших машин, Unix shell (интерпретатор для команд, вводимых в Unix-консоль) был спроектирован как полностью интерпретируемый язык программирования. Даже тогда было распространено написание программ полностью на shell или использование shell для написания связующей логики, объединяющей встроенные утилиты и нестандартные программы на С в целостные системы, эффективность которых была больше, чем сумма эффективности составляющих частей. В классических вводных книгах по Unix-среде (таких как "The Unix Programming Environment" [39]) подробно рассматривается данная тактика, и это вполне обосновано: она была одной из важнейших нововведений операционной системы Unix.
- Операционная система UNIX - Андрей Робачевский - Программное обеспечение
- Основы программирования в Linux - Нейл Мэтью - Программное обеспечение
- Архитектура операционной системы UNIX - Морис Бах - Программное обеспечение
- Windows Vista - Виталий Леонтьев - Программное обеспечение
- Изучаем Windows Vista. Начали! - Дмитрий Донцов - Программное обеспечение
- Разработка приложений в среде Linux. Второе издание - Майкл Джонсон - Программное обеспечение
- Microsoft Windows XP Professional. Опыт сдачи сертификационного экзамена 70-270 - Владислав Карпюк - Программное обеспечение
- Windows XP. Компьютерная шпаргалка - Тимур Хачиров - Программное обеспечение
- Linux - Алексей Стахнов - Программное обеспечение
- Windows Vista. Мультимедийный курс - Олег Мединов - Программное обеспечение