Файл: Обзор языков программирования высокого уровня (Современные языки программирования).pdf
Добавлен: 31.03.2023
Просмотров: 72
Скачиваний: 2
Введение
Прогресс не стоит на месте, появляются новые классы задач, возрастают требования к существующим решениям. В ответ на это совершенствуются имеющиеся языки программирования, появляются новые, нередко предназначенные для наиболее эффективного использования в определенной области. Встает вопрос о правильном выборе языка программирования для решения поставленных задач. И для этого необходимо понимать, чем отличаются языки программирования, каковы их сильные и слабые стороны, в каких областях они показывают себя с лучшей стороны.
Актуальность темы исследования заключается в том, что языки программирования в той или иной мере работают с данными, которые в большинстве случаев организованы в динамические структуры. В различных языках может по-разному решаться вопрос работы с ними. Где-то нужно самостоятельно выделять и освобождать память, оперировать указателями. В других случаях имеется автоматическое управление памятью, и эта обязанность возложена на сборщик мусора. Но даже в сценарных языках программирования нужно правильно выбирать структуры данных для решения тех или иных задач, исходя из их особенностей, используемых алгоритмов. А в высокопроизводительных программах помимо указанного необходимо учитывать и другие параметры, такие как скорость доступа к элементам, время удаления и добавление новых элементов, размер используемой памяти и так далее. Для этого требуются знания о внутреннем представлении динамических структур, достоинствах и недостатках различных подходов.
Также базовые динамические структуры являются основами для организации данных в более сложную иерархию. Как прочный дом не построить на шатком фундаменте, так и более-менее сложные программы не написать без понимания динамических структур.
Объект исследования – языки программирования высокого уровня.
Предмет исследования – динамические структуры данных, организация данных в списковые структуры.
Цель работы – провести анализ современных языков программирования высокого уровня, рассмотреть основные динамические структуры данных, продемонстрировать организацию данных в списковые структуры.
Задачи исследования:
- провести анализ литературы по выбранной теме;
- рассмотреть современные языки программирования высокого уровня;
- классифицировать и сравнить языки программирования по различным критериям;
- определить принципы построения динамических структур данных, выделить их достоинства и недостатки;
- рассмотреть основные динамические структуры данных;
- написать программу, демонстрирующую работу с данными в списковой структуре.
В работе использованы научные произведения таких авторов, как Седжвик Р., Прата С., Вирт Н., Страуструп Б., Поляков К.Ю. и другие.
Языки программирования высокого уровня
Согласно ГОСТ 19781-90, языком высокого уровня называется язык программирования, понятия и структура которого удобны для восприятия человеком. Из этого определения следует, что существуют языки и низкого уровня, которые не так удобны для восприятия. В чем тогда заключается удобство, можно ли его как-то охарактеризовать, какие возможности языка способствуют удобству восприятия?
Для ответа на эти вопросы следует определить критерии классификации и сравнить языки программирования.
Классификация языков программирования
Существуют различные классификации языков программирования, рассмотрим некоторые из них.
Одним из основных критериев является уровень языка программирования, то есть глубина абстракции, на которой позволяет работать язык. По этому критерию выделяют:
1. Языки низкого уровня. При программировании на них приходится непосредственно оперировать памятью и регистрами процессора. Они рассчитаны на определенный тип компьютера, на использование его особенностей. Первыми были машинные языки программирования, в которых регистры, данные, адресация памяти и команды представлены непосредственно в двоичных кодах. Естественно, программирование в таких условиях превращается в довольно сложную и трудоемкую задачу. Для ее упрощения стали разрабатываться языки ассемблера, позволяющие представлять двоичные коды в виде удобных для человека обозначений. Также появилась возможность использовать макросы, что положительно сказалось на переносимости программ и повторном использовании кода. Но по-прежнему сохранилась привязка к особенностям аппаратного обеспечения, поэтому перенос программ на другую архитектуру остался затруднителен.
В настоящее время чаще всего ассемблер используется для написания архитектурно-зависимого слоя, например, в операционных системах, или критичных участков программ, требующих максимального быстродействия, например в кодеке X264. Ассемблер также используется для программирования устройств с сильно ограниченными ресурсами.
2. Языки высокого уровня. Они позволяют абстрагироваться от аппаратного обеспечения, что дает возможность писать переносимый код и использовать более удобные для восприятия и работы понятия. Это способствует быстрой разработке программного обеспечения и уменьшению количества ошибок в нем. Часто ценой этих удобств являются более высокие требования к вычислительным ресурсам.
Подавляющее большинство кода сейчас пишется на языках программирования высокого уровня, их мы и будем рассматривать.
Существует огромное количество языков программирования [23]. Вполне закономерным будет вопрос, чем они отличаются, зачем создавать все новые и новые языки? Для ответа на этот вопрос необходимо рассмотреть другие критерии классификации.
Перед исполнением языки высокого уровня должны быть преобразованы в язык, понятный компьютеру. Для этого существует два основных подхода [17].
Компиляция — процесс преобразования исходного текста программы, написанного на языке высокого уровня в машинный язык, близкий к нему язык или в объектный модуль. Примерами современных компилируемых языков программирования являются C, C++, Objective-C, Go.
Интерпретация — поочередный анализ, обработка и выполнение команд высокоуровневого языка без предварительной компиляции. Часто интерпретируемыми языками программирования называют Python, Ruby, JavaScript, но это не всегда так и зависит от реализации языки программирования.
Таблица 1 – Сравнение компиляции и интерпретации
Критерий |
Компиляция |
Интерпретация |
Скорость работы |
Высокая |
Довольно низкая, так как происходит пооператорное выполнение |
Потребляемые ресурсы |
Минимальны |
Дополнительные расходы, особенно памяти |
Переносимость |
Высокая вероятность необходимости переписывания части кода для переноса на другую платформу |
Работает везде, где есть интерпретатор для данного языка |
Время компиляции |
Ощутимо для больших проектов |
Не требуется |
Наличие интерпретатора |
Не требуется |
Требуется предварительная установка |
Вероятность ошибок |
Ниже из-за анализа кода во время компиляции |
Даже самые простые ошибки (опечатки) могут нарушить работу во время выполнения очередной строки |
Как видно из таблицы 1, у каждого метода есть свои достоинства и недостатки. Указанные варианты трансляции являются диаметральными подходами, и в современных реализациях спецификаций языков программирования часто используются комбинированные подходы [17]. Примером промежуточного решения является байт-код, когда исходный код программы компилируется в машинно-независимый псевдокод виртуальной машины, а затем либо интерпретируется в машинный код (Python, Ruby), либо компилируется «на лету» в машинный код (Java). Такой подход позволяет добиться части важнейших преимуществ обоих методов, таких как высокая скорость выполнения и переносимость кода, но сохраняются и недостатки в виде высокого потребления ресурсов (особенно памяти) и необходимости установленной виртуальной машины.
По степени ориентации на решение определенного класса задач языки программирования разделяют на языки общего назначения и предметно-ориентированные (DSL – Domain Specific Language). Первые (C, C++, Java, Python…) являются универсальными и позволяют решать довольно широкий класс задач, вторые специализируются на определенной области применения, благодаря чему есть возможность оперировать терминами, наиболее приближенными к предметной области. В качестве примеров можно привести HTML, SQL, Postscript, PDF, Tex. Использование предметно-ориентированных языков дает ряд преимуществ, таких как высокая доступность для целевой аудитории, быстрота и эффективность разработки, легкость понимания и сопровождения [18]. Недостатком можно считать ограниченные возможности переноса в другие предметные области. Из существующих языков программирования именно предметно-ориентированные занимают значительную долю, и в будущем их количество будет только расти.
Также существует разделение языков на два класса: императивные (процедурные) и декларативные. В первых описывается сам процесс в виде инструкций, которые изменяют состояние программы и данных. Все ниже рассматриваемые языки программирования относятся к этой категории. Во вторых описывается логика вычислений, что должно быть выполнено, а не как. В качестве примера декларативных языков можно привести Ant, Prolog, SQL.
Современные языки программирования
Разобравшись в критериях классификации и причинах многообразия языков программирования, нужно определиться, какие из языков являются актуальными на сегодняшний день и почему. Для этого воспользуемся рейтингом TIOBE [24], в котором оценивается популярность языков программирования на основе подсчетов количества запросов по ним.
1.С (Си) — компилируемый язык программирования общего назначения. Характеризуется близостью к аппаратному обеспечению, высоким быстродействием и эффективным использованием ресурсов [13]. Его компиляторы существуют для самых различных платформ, что говорит о высокой переносимости. Но эта гибкость и мощь не дается даром — программисту приходится работать на довольно низком уровне: выделять и освобождать память, оперировать указателями, воспринимать строки как последовательность байт и так далее. Благодаря этому его в шутку называют универсальным ассемблером. Тем не менее язык Си оказал не только огромное влияние на последующие языки программирования, такие как Java, C++, C#, Objective-C, но и остается одним из самых популярных языков на данный момент, широко используется в разработке системного программного обеспечения, встраиваемых систем.
Стандартная библиотека Си практически не содержит динамических структур, но некоторые реализации (например, glib) предоставляют списки, деревья и другие структуры, также можно реализовать все это самостоятельно или воспользоваться сторонними библиотеками.
2. C++ создавался как Си с классами, в который были добавлены возможности для объектно-ориентированного программирования. Он не только сохраняет практически все преимущества языка Си, но и позволяет использовать более высокоуровневые абстракции, такие как классы и шаблоны, добавлена работа с исключениями, что положительно сказывается на читаемости и дальнейшей поддержке кода. Один из основных принципов – не нужно платить за то, что не используется [21]. К примеру, те же исключения отрицательно сказываются на быстродействии программы, но если они не используются, то никаких расходов на них не будет. Казалось бы, что имея всю эту мощь и гибкость, C++ должен быть идеальным языком программирования. Но есть и обратная сторона медали – для умелого использования языка требуется достаточно высокая квалификация разработчика, так как язык сложен, и имеется множество способов «выстрелить себе в ногу».
C++ пользуется популярностью в научной и финансовой среде, разработке игр и другого программного обеспечения, требующего максимальной производительности. В последнее время широко используется в разработке приложений для мобильных устройств, когда их нужно переносить на другие платформы с минимальными изменениями, например, с IOS на Android.
Стандартная библиотека С++ предоставляет различные динамические структуры, вопрос встает больше в том, как правильно выбрать динамическую структуру для конкретной задачи.
3. Java создавался под влиянием C++ и является полностью объектно-ориентированным языком программирования [1]. Основными целями при ее создании были кроссплатформенность, когда программа не зависит или почти не зависит от типа процессора, и возможность командной работы над большими и сложными проектами, где немаловажными факторами являются скорость разработки и надежность самих программ. Для этого была реализована виртуальная машина (JVM — Java Virtual Machine), которая работает с промежуточным байт-кодом. По сути это была первая реализация двухэтапной модели выполнения программ [9]. Язык не предоставляет низкоуровневые инструменты вроде указателей и адресной арифметики, ручного управления памятью, этим в Java занимается сборщик мусора. Для повышения надежности кода и избавления от потенциальных ошибок также было решено отказаться от множественного наследования и перегрузки операторов.