Файл: Классификация языков программирования. Критерии выбора среды и языка разработки программ (Основная терминология программирования).pdf

ВУЗ: Не указан

Категория: Курсовая работа

Дисциплина: Не указана

Добавлен: 28.03.2023

Просмотров: 322

Скачиваний: 2

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

СОДЕРЖАНИЕ

ВВЕДЕНИЕ

1. Теоретические концепции языков программирования и программных сред

1.1. Основная терминология программирования

1.2. Классификация языков программирования по способу исполнения программ

1.3. Классификация языков программирования по уровню детализации

1.4. Классификация парадигм, реализуемых языками программирования

1.5. Критерии выбора сред и языков программирования

2. Некоторые современные языки программирования и их сравнение

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

2.2. Язык программирования C++

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

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

2.5. Язык программирования C#

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

3. Некоторые современные среды разработки и их сравнение

3.1. Среда разработки Microsoft Visual Studio

3.2. Среда разработки NetBeans

3.3. Среда разработки Eclipse

3.4. Сравнительный анализ сред разработки приложений с точки зрения одной из отраслей

ЗАКЛЮЧЕНИЕ

СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

  • Код, написанный программистом, транслируется в компактный промежуточный код виртуальной машины.
  • При интерпретации промежуточного кода для исполнения, виртуальная машина перед первым использованием каждого отдельного участка кода фактически компилирует и временно сохраняет его в памяти.
  • Повторное использование уже скомпилированного фрагмента кода происходит также быстро, как и при классической компиляции: его не требуется транслировать в машинный язык заново.
  • Пока участок кода не используется, он может не компилироваться[30], что позволяет избежать затрат ресурсов, присущих обычной компиляции.

1.3. Классификация языков программирования по уровню детализации

Детализированность алгоритмов на ЯП определяет его уровень. Языки высокого уровня удобны для восприятия человеком[31]. Также, уровень языка тесно связан со степенью его зависимости от аппаратного обеспечения. Чем выше ориентация ЯП на конкретную архитектуру набора команд и чем больше в нём технических деталей[32], ухудшающих восприятие кода программистом, тем ниже уровень языка. Всего по этим критериям выделяют следующие категории языков[33][34]: машинные языки, ЯП ассемблерного типа, и высокоуровневые ЯП. Также, частным случаем уровня детализации работы с аппаратным обеспечением может являться способ работы языка с памятью.

Начнём с машинных языков. Данная категория языков самая древняя, и, по сути, является не языком, а способом кодирования машинных инструкций, предложенным Джоном фон Нейманом в 1945 году. Любой современный компьютер является реализацией множества его идей, включая эту. Каждая команда машинного языка, построенная по принципам фон Неймана, целиком и полностью состоит из двоичных цифр, объединённых в минимальные блоки (байты и слова)[9]. Таким образом, текстовая запись родного для компьютера машинного кода будет представлять собой набор нечитабельных для неподготовленного человека чисел, независимо от того, в какой системе счисления эти числа визуализированы. Программировать таким способом крайне тяжело и затратно, а код полностью зависим от процессора[35].


В связи с очевидным неудобством программирования в машинных кодах, команды процессоров были сгруппированы в соответствии с их функциональностью с точки зрения человека, и им были присвоены читабельные формальные наименования[36]. Так появились ассемблеры – программы для трансляции формальной алгоритмической записи инструкций процессора (т.н. язык ассемблера) в их машинную форму[37]. Язык ассемблерного типа, в отличие от машинного кода, может использоваться для наглядного и относительно читабельного описания алгоритма программы: он позволяет не отвлекаться на фактическое вычисление машинных инструкций[38]. Ассемблеры зависимы от набора команд процессора, а ассемблерные инструкции - повторяют процессорные инструкции[39].

Также существует очень специфический независимый от процессора подвид ассемблеров, появившийся в эпоху виртуальных машин и JIT-компиляции. Он транслирует инструкции не в машинный код аппаратного процессора, а в промежуточный код виртуальной машины[40]. Ассемблеры этого типа, таким образом, зависят не от аппаратной платформы, а от виртуальной машины и программной платформы. Такие языки чрезмерно специфичны, использование ассемблеров виртуальных машин на практике – явление довольно нечастое[41].

На этом эволюция языков программирования в плане оптимизации работы программиста не закончилась. Программировать на машинных и ассемблерных языках сложно, из-за необходимости думать не над решением прикладной задачи, а над описанием действий аппаратного обеспечения. Если задача, которую решает программист, достаточно масштабна, - низкоуровневое программирование только переусложнит её. Именно для облегчения условий работы прикладных программистов, и повышения их сосредоточенности на текущей задаче, и были разработаны языки высокого уровня[42]. Высокоуровневые лексемы не связаны прямо с функционалом процессора, а ориентированы на использование в прикладных целях, они сделаны похожими на естественные языки[43] и/или символическую математику, чтобы быть понятными программисту[44].

Помощь в реализации фактических конструкций высокоуровневых языков возложена на программный интерфейс приложений (API) и двоичный интерфейс приложений (ABI). Первый интерфейс может применяться силами самого программиста. Он включает различные высокоуровневые средства, помогающие программисту в решении прикладных задач. Ответственность за внутреннюю реализацию API лежит на его разработчиках. Второй интерфейс программист в большинстве случаев не может использовать явно, но именно он отвечает за реализацию семантики языка операционной системой и аппаратным обеспечением, отвечая за двоичную совместимость программного обеспечения [21].


Кроме этого, у высокоуровневых языков иногда бывает автоматизирована работа с памятью. Такую систему называют сборкой мусора [18]. В противовес преимущественно высокоуровневой сборке мусора, в высокоуровневых и низкоуровневых ЯП может существовать и явное освобождение памяти. Для явного оперирования памятью в высокоуровневых языках программирования, созданы специальные правила и идеомы, например, «resource acquisition is initialization» (RAII) в языке C++[45].

1.4. Классификация парадигм, реализуемых языками программирования

В связи с требованиями по решению прикладных задач, а также в связи с необходимостью упростить правила программирования, сделав их исходные тексты схожими с человеческой логикой, появлялось множество парадигм программирования. Рассмотрим наиболее устоявшиеся, независимо от классификатора, парадигмы[46][47][48]:

  • императивная
  • функциональная
  • декларативная
  • объектно-ориентированная

Рассмотрим сначала императивную парадигму. Минимальный лексический элемент управления у языков данной группы – оператор[49]. Действия над данными выражаются в виде последовательностей инструкций [2], выполнение каждой из которых изменяет состояние компьютера. Процедурная схема идеально отражает особенности компьютерной архитектуры Джона фон Неймана [8, с. 16]. Императивная программа представляет собой последовательность инструкций, выполняемых по порядку. Также присутствуют циклы – последовательности инструкций, которые могут выполняться по нескольку раз до выполнения определённого условия [50]. Процедурами называются именованные блоки машинных инструкций, которые можно вызвать удалённо из разных участков кода [1]. Возможен рекурсивный вызов процедур, однако такие приёмы программирования следует использовать осторожно из-за ограничений стековой памяти на многих компьютерных архитектурах [7, с. 99 – 101]. Любой императивный язык должен показывать, как именно должен быть реализован тот или иной алгоритм; зато, у процедурных программ высокая скорость выполнения[51]. Согласно некоторым расширенным классификациям, благодаря этому фактору, только процедурные языки могут быть низкоуровневыми[52]. Известным примером языка, созданного для процедурного программирования, является C.


Функциональная парадигма (также называемая в некоторых источниках[53] аппликативной) была предвосхищена математиком А. Чёрчем, в 30-х годах XX века создавшим лямбда-исчисление, в некотором смысле предок любого функционального языка [29].

Основная идея функционального программирования (ФП) – оперирование функциями, подвидом процедур [1], умеющим возвращать значение[54], для работы с данными. Из простых функций составляются более и более сложные функции, пока из начальных данных не будет получен желаемый результат [8, 15]. Ещё одной особенностью функциональной парадигмы является сознательный отказ от использования переменных. Долгое время реализация лямбда-исчисления на фон-неймановских компьютерных архитектурах считалась крайне сложной[55]. На относительно современных компьютерах (конца XX века – начала XXI века) функциональное программирование наконец-то обрело достойную реализацию. Это связано в основном с развитием параллельных вычислений; в частности, параллелизм может быть описан функциональным языком более лаконично, чем императивным, также эти технологии хорошо комбинируются. Функциональные языки программирования используются в математическом ПО и для создания Искусственного Интеллекта. Как и процедурное программирование, ФП демонстрирует, как именно должно выполняться то или иное программное действие[56], однако функциональное программирование часто противопоставляется императивному[57]. Классическим примером языка, созданного для ФП, является LISP.

Декларативная группа языков, как и функциональная группа, оперирует действиями для достижения конечного результата. На практике иногда даже отождествляют эти два понятия[58]. Однако парадигма декларативного программирования строится вокруг утверждения, что каждый шаг действий не должен описываться явно. Способ решения задачи в декларативных ЯП не описывается; вместо этого, основным предметом описания является сама задача и условия, при которых она может быть выполнена.

В некоторых источниках эта группа языков называется языками с системой правил[59], согласно же другим – языки системы правил являются лишь наиболее показательным подвидом декларативных языков[60]. Языки системы правил, также известные как языки логического программирования, не имеют чёткого порядка выполнения алгоритмов. Вместо этого, единственным, что влияет на порядок выполнения логических программ, являются т.н. разрешающие высказывания (условия) [8, с.18]. В программе задаются факты, являющиеся по сути своей данными, и аксиомы, связывающие каждое потенциальное действие программы с проверкой разрешающего условия. Действие будет выполнено только при соответствии условию. Самым известным языком логического программирования является Prolog.


Объектно-ориентированная парадигма представлена множеством языков, таких как C++ или Java. По данным некоторых источников, она значительно повышает производительность труда программиста[61][62], позволяя работать с данными, имеющими прямое отношение к предметной области программы. Для этого, программа разбивается на осмысленные модули, именуемые объектами, и на функции, которые можно выполнить с тем или иным объектом, называемые методами. Важнейшую роль тут играют типы данных. Каждый объект имеет свой тип, и может наследовать черты объектов другого типа. Типы описываются программистом посредством своеобразных чертежей - классов[63].

Разработка объектно-ориентированных программ начинается с построения иерархий из классов [8, с. 19]. Некоторые готовые классы программист может получить из средств API [21]. Основные особенности классов и их методов, ставшие стандартом парадигмы объектно-ориентированного программирования (ООП):

- Внутренняя информация классов должна быть инкапсулирована, доступ к ней извне должен быть скрыт либо жёстко регламентирован; это обеспечивает контроль над несанкционированным или случайным произвольным изменением данных[64].

- Одни классы могут наследовать черты других классов, при этом производные объекты автоматически считаются также и объектами унаследованного класса[65].

- Полиморфизм ad-hoc: возможность создать в разных классах, объединённых в одну иерархию, разные реализации наследуемого метода, и ссылаться на них из классов и методов внешнего контекста, как на один и тот же, несмотря на различия в реализации[66].

1.5. Критерии выбора сред и языков программирования

IDE должна реализовывать нужную модель разработки максимально удобно для программиста[67]. Данные вопросы, на примере платформы Java, изучала во второй половине 2000-х исследовательская группа в Вестминстерском Университете. В ходе исследования было решено создать несколько групп критериев. Часть критериев, независимая от Java [20]:

  • Интерфейс. Для оценки интерфейса IDE требовалось ответить на следующие вопросы: 2 вопроса про автодополнение кода, насколько хорош редактор кода, понятен и дружественен ли интерфейс, особенности навигации в IDE.
  • Развёртывание, тестирование и поддержка. Несколько вопросов о проверке кода на ошибки, тестировании, системе справки и поддержки, предоставляемой программисту.
  • Возможности подключения баз данных, различных сетевых служб. Производительность IDE на пике работы.