Языки программирования

  1. Лирическое наступление
  2. Компилируемые языки
    1. Assembler
    2. C
    3. C++
    4. Java
    5. C#
  3. Интерпретируемые языки
    1. Perl
    2. Python
    3. Ruby
  4. Юношам, обдумывающим житье

Лирическое наступление

В этом опусе рассмотрено несколько популярных платформаннонезависиых языков программирования. Рассматриваются только процедурные (императивные) языки. Функциональные (Lisp, Hasckell, ML...) и логические (Prolog) хотя и интересны сами по себе, но применяются гораздо реже процедурных. Но все равно рекомендуется хотя бы ознакомиться с ними, чтобы иметь представление о разных парадигмах программирования.

В тексте нет никаких ссылок, так как их несложно найти на поисковых серверах.

Компилируемые языки

Программы, написанные на компилируемых языках, с помощью специальной программы-транслятора (компилятора) один раз преобразуются непосредственно в команды процессора. Таким образом, для своей работы они не требуют системы программирования и работают гораздо быстрее (в десятки раз) интерпретируемых программ. Однако, малейшее изменение текста программы требует выполнение перекомпиляции, которая может идти довольно долго (до нескольких десятков минут даже на мощных машинах).

Assembler

Язык Ассеблера позволяет писать наиболее эффектиные (как по скорости выполения, так и по потребелнию ресурсов), непереносимые, специфичные для конкретной платформы программы. Программирование на этом языке чрезвычайно трудоемко. Поэтому Assembler в настоящее время применяется только для разработки драйверов, машиннозависимых фрагментов операционных систем, для оптимизации кода, генерируемого компилятором, программирования микроконтроллеров.

Однако, контроллеры все чаще программируются на C, а эффективная оптимизация программ достигается не за счет ассемблерных вставок, а за счет выбора более подходящего алгоритма.

С

Язык С был разработан в начале 70-х годов для разработки переносимых системных программ (пример - ОС UNIX). Т.е. язык разрабатывался системными программистами для системных программистов. Такие цели и определили характеристики языка, который часто называют высокоуровневым ассемблером для ленивых. Одной из целей разработчиков была разработка ЯП для получения маскимально эффективных программ даже за счет усложнения жизни программисту. В языке есть конструкции (например, операторы инкремента/декремента, сдвига), которые отображаются непосредственно в машинные инструкции. При этом они отобраджаются в инструкции соотвтетствующего процессора. Т.е. мы получаем с одной стороны програмы почти такие же эффективные, как написанные на ассеблере, а с другой - программа без изменений исходного кода может быть откомпилирована на другом процессоре. Примерами могут служит различные вариант UNIX, которые без изменений (за исключением очень небольшой машинозависимой части) компилируются под десятки различных платформ. Еще одним признаком низкоуровневости языка является наличие в нем указателей. Указатели, являющиеся инструменом косвенной адресации, позволяют сделать программу более гибкой и работать непосредственно с аппаратурой компьютера. Однако, язык не предоставляет никаких средств защиты от неправильной работы с указателями, что является частым источником ошибок (иногда очень трудно локализуемых).

С является достаточно прозрачным языком. Для его изучения необходимо понять лишь несколько базовых концепций. С другой стороны, язык очень беден. Например, в нем даже нет средств ввода-вывода. Вся мощь языка обеспечивается его библиотеками функций, которых очень много на все случаи жизни. Объем знаний, который необходим для нормально использования библиотеки может быть очень большим, особенно если в библиотеке есть "подводные камни".

Так как при программировании на С программист пишет почти все сам, то логика программы является довольно понятной (по крайней мере первое время, пока программист ничего не забыл :) Однако с ростом сложности задачи процесс программирования становится все более трудоемким.

С++

С++ является объектно-ориентированным языком (ООЯ). Разработчик С++ - Бьерн Страуструп - хотел разработать ООЯ на базе С. Объектно-ориентированный подход пытается писать программы не в терминах ЭВМ, а в терминах нашей суровой действительности (предметной области). Например, необходимо написать программу, которая будет обрабатывать информацию об автомобилях. В программе на С был бы набор переменных, описывающих авто (марка, объем двигателя и т.д.) и набор функций для работы с этими переменными. Может быть переменные были бы объединены в структуру. В С++ был бы класс, описывающий авто и содержащий методы (функции в терминах С), для обработки информации об автомобиле. Вроде бы подход С и С++ почти похож (тем более, что классы являются дальнейшим развитием структур). Но в С++ есть несколько кардинальных отличий:

  1. Инкапсуляция (сокрытие данных). Сведения о том, как хранится информация в классе от программиста, его использующего, скрыта. Например, если в классе есть метод, для получения объема двигателя, то программисту безразлично как эта информация определяется: или вычисляется или хранится в отдельной переменной. Такой подход, во-первых, уменьшает количество сущностей, которые необходимо знать программисту (принцип бритвы Оккама), во-вторых предоставляет большую свободу разработчику класса. Разработчик может как угодно менять внутренне содержимое класса, не влияя на программы, использующие этот класс. В С эта информация доступна пользователю и есть соблазн использовать ее на прямую, что может повлечь за собой необходимость переделки всей программы. Например, если раньше для объема двигателя применялась переменная, и программа к ней обращалась, то при переходе к расчету объема двигателя с помощью функции, программу надо переделывать для использования этой функции.
  2. Наследование. Автомобиль является частным случаем транспортного средства. ООЯ позволяют строить новые, более специализированные, типы данных на базе уже существующих.
  3. Полиморфизм. Несколько функций могут иметь одно и тоже значение. Это применяется когда для разных типов надо выполнять похожие действия. Зачатки полиморфизма есть и в обычных языках. Например символом '+' обозначается сложение и целых и вещественных чисел. Однако эти операции для разных типов данных выполняются по-разному.
Эти особенности С++ упрощают процесс программирования.

Прототипы функций, ссылочные типы данных, строгая типизация являются хоть какой-то защитой от ошибок программирования. Использование указателей в С++ можно значительно уменьшить, а в Java, который является дальнейшим развитием С++, указателей нет вообще.

Удобной особенностью С++ является механизм виртуальных функций, которые обеспечивают дополнительную гибкость.

Также у С++ гораздо больше библиотек. Например, Standart templates library (STL) содержит множество классов для различных типов данных (стеков, списков, очередей и т.д.) и алгоритмов (поиска, сортировки и т.д.). Поэтому при программировании на С++ редко когда надо "изобретать велосипед". Однако, надо очень хорошо знать используемые библиотеки.

Недостатком С++ является то, что он делает по сравнению с С еще больше неявных вещей. Например, в С можно было счтитать, что выполнение программы начинается с запуска функции main (что на самом деле не совсем так) и заканчивается, когда завершается main (что тоже не так). В С++ же, если объявлены глобальные объекты, то сначала будут вызываться их конструкторы, а только потом - main.

Т.к. С++ применяется для программирования более сложных задач, чем С, то квалификация программиста должна быть достаточно высока. Например, он должен понимать разницу перед присваиванием и инициализацией, что означет "объекты равны": то ли одинаковы их значения, то ли - это один и тот же объект и т.д. Чтобы писать качественные программы язык надо знать очень хорошо.

Еще один недостаток - больший объем кода, который генерирует компилятор С++.

По этой причине программирование на С++ с одной стороны легче чем на С, с другой - сложнее. Последнее связано с тем, что С++ пытается быть столь же эффективен как и С.

Java

Java является дальнейшим развитием идей C++. Разработчик Java - фирма SUN - попыталась учесть и исправить недостатки С++. Например, как уже говорилось выше, в языке отстутствуют указатели, что уменьшает возможность внесения ошибок. Также в Java нет еще некоторых возможностей C++ - множественного наследования, перегрузки операторов. С другой стороны в стандартную библиотеку языка входит набор классов для построения графического интерфейса - GUIC++ для этого используются библиотеки сторонних разработчиков).

Однако, основным отличием Java является концепция Виртуальной Машины Java - Java Virtual Machine (JVM). Программы на Java компилируются в команды не конкретного процессора (Intel x86, PowerPC и т.д.), а какого-то виртуального. Такой подход позволяет выполнить компиляцию программы один раз и запускать ее на тех платформах, где установлена JVM. С одной стороны эта особенность упрощает жизнь программисту (которая и без того "тяжела и неказиста"), а с другой требует установленной виртуальной машины, которая потребляет дополнительные ресурсы системы (и не мало).

Java появилась в эпоху бума Internet, поэтому SUN (может из маркетинговых соображений или в пику Microsoft) стала продвигать этот язык как инструмент для разработки небольших программ для Web-страниц. Такие программы, в отличие от нормальных приложений (applications), называют апплетами - applets (этот термин иногда переводили как "приложеньице").

C#

"Java от Microsoft". Язык, очень похожий на Java, по крайней мере на первый взгляд. Разработан Microsoft для платформы .Net (dot net). Технология .Net пока доступна только для Windows, поэтому язык является непереносимым. Спецификации dot net опубликованы. Борцы за свободное ПО даже уже выпустили первую версию свободной реализации это технологии (проект Mono). Однако, Microsoft их поступок вроде бы не нравится. Интересно, почему :).

Так как язык не вполне переносим и я его не знаю (вторая причина более важна), он рассматриваться не будет.

Интерпретируемые языки

Программы, написанные на интерпретируемых языках, выполняются на прямо процессором, а специальной программой-интерпретатором. Из-за этого они работают гораздо медленее исполняемых файлов. Но, во-первых, мощности современных компьютеров достаточно для многих интерпретируемых программ (пользователь все равно соображает гораздо медленее, чем работает программа). Во-вторых, процесс программирования является более гибким и быстрым, например, из-за отсутствия стадии компиляции. Для многих интерпретируемых языков версии для Windows позволяют получать независимый исполняемый exe-файл. Этот файл просто содержит внутри себя интерпретатор и необходимые компоненты, поэтому является довольно большой (единицы-десятки мегабайт). Однако в настоящее время такой размер не является проблемой. В системах UNIX необходимые интерпретаторы обычно установлены.

Perl

Язык разработан ленивым UNIX-администратором Ларри Уолом, которому надоело руками разгребать многочисленные файлы журналов программ (log-файлы). Ларри был уже достаточно испорчен UNIX'ом, поэтому на можно очень быстро написать программу, которая будет выполнять достаточно сложные действия и умещаться две-три строки. При этом она будет чрезвычайно непонятна новичкам. Основное назначение Perl - обработка текста. Но существуют различные привязки (bindings, биндинги), позволяющие программам на Perl использовать библиотеки других языков (обычно C/C++), например PerlGTK. На Perl даже написан оконный менеджер.

Python

Этот интерпретируемый ООЯ в последнее время очень популярен. Python является языком общего назначения, содержит множество встроенных высокоуровневых типов данных (списки, стеки, хэши, кортежи и т.д.), легко расширяется с помощью C++. Для Python написано много дополнительных библиотек и привязок к библиотекам C/C++. Интерпретатор Python'а можно встраивать в другие программы. Примером может служит OpenOffice. Характерной особенностью языка является чувствительность к отступам в тексте программы, с помощью которых выполняется выделение обдельных программных блоков. Объектно-ориентированный подход в Python несколько отличается от подхода C++. В Python также присутствуют элементы функционального программирования (например, конструкция lambda).

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

В настоящее время известна одна реализация интерпретатора Python, которая существует для всех распространенных платформ и бесплатна даже для коммерческого применения.

Процесс разработки языка очень похож на то, как герои Джером К. Джерома готовили ирландское рагу. Поэтому, возможно, Python является несколько перегруженным концепциями и конструкциями.

Ruby

Это также ООЯ, который очень популярен в Японии. Однако в остальном мире менее известен, чем, например, Python. По этой причине для Ruby написано меньше библиотек, чем для Python. С другой стороны, язык является более целостным. Если в Python поддержка объектно-ориентированной парадигмы была добавлена, то Ruby изначально разрабатывался как ООЯ. Возможно, со временем для Ruby будет также много расширений, как и для Python.

Юношам, обдумывающим житье

На С следует разрабатывать не очень сложные программы, программы с не очень сложными данными или когда размер программы очень существенен. Для более сложных проектов имеет смысл использовать C++ или Java (когда некуда девать вычислительные ресурсы или лень писать многоплатформенное приложение и выполнять компиляцию для каждой платформы).

А вообще писать программы надо не на С или С++, а на других (часто интерпретируемы) языках. Эти языки менее эффективны с точки зрения использования ресурсов, но, во-первых, современные компьютеры достаточно мощные и имеют много ресурсов, а, во-вторых, программировать на этих языках проще.

Copyleft, 2005 Vadim A. Khohlov aka xvadim (xvadim AT newmail.ru)