1.1. Теория

Содержание

1.1.1. Разработка программного обеспечения сегодня

1.1.1.1. Программы вокруг нас

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

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

На Рисунках 1.1.1‑1.1.3 приведены примеры компьютерных систем и приложений.

_images/01_01_01.png

Рисунок 1.1.1 - Система управления истребителя СУ-35 51

_images/01_01_02.png

Рисунок 1.1.2 - Компьютерная система на фондовой бирже 52

_images/01_01_03.png

Рисунок 1.1.3 - Система дистанционного банковского обслуживания Сбербанк.Онлайн 53

В общем случае программное обеспечение делится на 2 типа: системное и прикладное (Рисунок 1.1.4).

_images/01_01_04.png

Рисунок 1.1.4 - Системное и прикладное ПО 54

К системному программному обеспечению относят:

Прикладное программное обеспечение включает «пользовательские» программы: текстовые редакторы, видеоплееры, игры и т.д.

Общая схема взаимодействия пользователя, программы, операционной системы и компьютера приведена на Рисунке 1.1.5.

_images/01_01_05.png

Рисунок 1.1.5 - Структура типичной компьютерной системы 55

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

1.1.1.2. Процесс разработки программного обеспечения

Программное обеспечения подразделяется на три основные группы:

  • заказное ПО;

  • ПО для корпоративного потребителя;

  • ПО для массового потребителя.

Они появлялись друг за другом с интервалом примерно в десятилетие.

В настоящее время процесс разработки программного обеспечения включает следующие подпроцессы:

1. Анализ требований

Задачи: сбор, анализ и документирование требований к программному обеспечению.

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

2. Проектирование

Задачи: определение внутренних свойств системы и детализации ее внешних (видимых) свойств на основе спецификация требований.

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

3. Программирование

Задачи: создание и использование алгоритмов и структур данных в рамках архитектуры и в соответствии со спецификацией требований.

Результат: рабочее программное обеспечение, выполняющее заданные функции.

4. Документирование

Задачи: создание проектной, технической, пользовательской и прочей документации, описывающей вопросы использования программного продукта.

Результат: документация к программному обеспечению.

5. Тестирование

Задачи: исследование продукта на соответствие спецификации требований, выявление возможных ошибок и исправление несоответствий.

Результат: доработанное программное обеспечение с учетом ошибок и исправлений.

6. Системная интеграция и Внедрение в эксплуатацию

Задачи: настройка ПО для работы в компьютерной экосистеме пользователя/заказчика, а также обучение конечных пользователей.

Результат: программное обеспечение, функционирующее и используемое целевыми пользователями.

7. Сопровождение

Задачи: оперативное реагирование на обнаруженные дефекты в работе программного обеспечения, новые требования и т.д.

Результат: материалы для запуска очередного цикла разработки.

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

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

_images/01_01_06.png

Рисунок 1.1.6 - Пример Agile-команды по разработке ПО 56

На Видео 1.1.1 приведено обобщенное описание профессий в сфере информационных технологий.

Видео 1.1.1 - Профессии в мире информационных технологий

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

1.1.1.3. Востребованность и зарплаты

Насколько рассмотренные выше направления работы в ИТ-сфере являются востребованными и перспективными? В Таблице 1.1.1 и приведены ТОП-10 самых востребованных и самых высокооплачиваемых профессий в России по данным портала EduNews.

Таблица 1.1.1 - ТОП-10 профессий в России по критериям: уровень оплаты, востребованность в народном хозяйстве, перспективность работы и возможности развития сотрудника 9

Востребованность

Профессия

1

Инженер

2

IT-специалист

3

Топ-менеджер

4

Врач

5

Пилот

6

Нефтяник

7

Эколог

8

Химик

9

Переводчик

10

Стоматолог

Краткий обзор зарплат специалистов ИТ-сферы приведен в исследовании 27 (на 2022 г.):

_images/01_01_06_1.jpg
_images/01_01_06_2.jpg

Примечание

Актуальную статистику зарплатных предложений можно посмотреть, например, на ресурсах Хабр Карьера или Superjob.

1.1.2. Компьютер, алгоритм и программа

Компьютер создавался как устройство для выполнения двух простых операций:

  • численных вычислений;

  • сохранения результатов этих вычислений,

но даже самый примитивный компьютер справляется с этими задачами намного быстрее человека. С тех пор мало что изменилось: используете Вы ноутбук, мобильное устройство или суперкомпьютер в научно-исследовательском центре - отличаться будет только скорость осуществления и объем запоминаемых вычислений.

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

В то же время человек по-прежнему определяет главное: как выполнять вычисления, предоставляя компьютеру набор инструкций, описывающих порядок действий для достижения некоторого результата. Такая последовательность инструкций традиционно называется алгоритмом. В свою очередь, алгоритм, записанный на формальном языке (языке программирования), который можно было бы «донести» до компьютера, называется программой.

1.1.2.1. Алгоритм: способы представления и свойства

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

  1. Словесная форма: запись на естественном языке.

    Для того, что узнать стоимость имеющихся яблок, необходимо:
    - узнать вес имеющихся яблок в кг.;
    - узнать стоимость 1 кг. яблок;
    - получить ответ, перемножив полученные величины.
    
  2. Графическая форма: изображения из графических символов, как правило, в специальной нотации.

    _images/01_01_01_i.png

    В качестве простой графической нотации описания алгоритмов часто используются блок-схемы, регламентируемые ГОСТ 19.701-90 «Схемы алгоритмов, программ, данных и систем. Условные обозначения и правила выполнения. В англоязычном ИТ-сегменте аналогом являются диаграммы Flowchart.

  3. Псевдокоды: полуформализованные описания алгоритмов на условном алгоритмическом языке.

    - завести величины X, Y, P вещественного типа;
    - ввести с клавиатуры вес имеющихся яблок в кг. как X;
    - ввести с клавиатуры стоимость 1 кг. яблок как Y;
    - P = X * Y;
    - вывести на экран P.
    
  4. Программная форма: тексты на языках программирования.

    Пример на Pascal:

    var
        x, y, p: real;
    
    begin
        readln(x, y);
        p := x * y;
        writeln(p);
    end.
    

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

Любой алгоритм должен обладать следующими свойствами:

  1. Дискретность: алгоритм разбивается на конечное число элементарных действий (шагов).

  2. Понятность: каждое из этих элементарных действий является законченным и понятным.

  3. Детерминированность: каждое действие должно пониматься в строго определенном смысле (пониматься однозначно).

  4. Массовость: по данному алгоритму должна решаться не одна, а целый класс подобных задач.

  5. Результативность: любой алгоритм в процессе выполнения должен приводить к определенному результату (в т.ч. отрицательному).

В качестве примера рассмотрим алгоритма кипячения воды в электрическом чайнике (с точки зрения человека), один из возможных вариантов которого мог бы выглядеть следующим образом:

-- НАЧАЛО --

определить, хватит ли в чайнике воды для заваривания чая
ЕСЛИ воды мало:
  - открыть кран с водой
  - налить воды в чайник
  - закрыть кран с водой
подключить чайник к сети
включить чайник
ПОКА вода греется:
  - прочитать новость в Интернете
  - посмотреть в окно

-- КОНЕЦ --

Любой алгоритм (в том числе и приведенный выше) необходимо усложнять и/или разбивать на дополнительные шаги до тех пор, пока он не будет удовлетворять всем 5 свойствам для конкретного исполнителя (человека, компьютера или кого-либо еще) (Видео 1.1.2).

Видео 1.1.2 - Как нужно намазывать бутерброд?

1.1.3. Вычислительные устройства: классификация и история

При наличии более-менее формализованного алгоритма, возникает вопрос - как можно «поручить» устройству его выполнение?

История знает 3 класса устройств, созданных человечеством для решения данной проблемы (Таблица 1.1.2).

Таблица 1.1.2 - 3 класса устройств

Класс

Пример

1

Выполнение определенной задачи

Обычный калькулятор, счеты и т.д.

2

Выполнение определенной задачи на произвольных (изменяемых) данных

Видеоплееры, CD-проигрыватель и др.

3

Выполнение произвольной (изменяемой) задачи на произвольных (изменяемых) данных

Современные компьютеры

Все такие устройства могут считаться компьютером (англ. Computer — «вычислитель»), под которым в широком смысле понимается любое устройство или система, способное выполнять заданную четко определенную изменяемую последовательность операций (численных расчетов и манипулирования данными, операции ввода-вывода). Используемое нами в повседневной жизни понятие «компьютер» - это электронная вычислительная машина (ЭВМ) - одна из реализация компьютера, которая подразумевает использование электронных компонентов в качестве ее функциональных узлов.

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

1.1.3.1. Класс 1 - Определенная задача

Изначально человечество шло по первому пути и вычислительные устройства были способны выполнять лишь заранее заложенные инструкции (как правило, математические вычисления), ограниченные конфигурацией самих устройств. Фундаментальный недостаток подобной архитектуры - необходимость полной физической переконфигурации для выполнения других задач.

К устройствам подобного типа можно отнести абак, счеты, арифмометр и логарифмическую линейку (Рисунки 1.1.7‑1.1.9).

_images/01_01_07.png

Рисунок 1.1.7 - «Паскалина» (1642 г.) - первое реально осуществленное и получившее известность механическое цифровое вычислительное устройство, изобретенное французским ученым Блезом Паскалем. Прототип устройства суммировал и вычитал пятиразрядные десятичные числа 57

_images/01_01_08.png

Рисунок 1.1.8 - Арифмометр - вычислительная машина, предназначенная для точного умножения и деления, а также для сложения и вычитания 58

_images/01_01_09.png

Рисунок 1.1.9 - Логарифмические линейка - аналоговое вычислительное устройство, позволяющее выполнять несколько математических операций. Принцип действия основан на том, что умножение и деление чисел заменяется соответственно сложением и вычитанием их логарифмов 59

Известная электронно-механическая машина Turing Bombe, созданная английским математиком, логиком и криптографом Аланом Тьюрингом, и использовавшаяся во время Второй мировой войны для расшифровки «Энигмы» (немецкой шифровальной машины) также являлась непрограммируемым устройством (Рисунок 1.1.10).

_images/01_01_10.png

Рисунок 1.1.10 - Дешифровальная машина Bombe 60

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

1.1.3.2. Класс 2 - Произвольные данные

Первой попыткой «программирования» устройства был ткацкий станок французского изобретателя Жозефа Мари Жаккарда (1801 г.), где вышивка определялась «динамически» - перфокартой . Перфокарта содержала информацию наличием или отсутствием отверстий в определенных позициях карты и в дальнейшем стала предшественником современных устройств ввода информации (магнитной ленты, дискет, дисков, флеш-памяти и др.) (Рисунки 1.1.11‑1.1.12).

_images/01_01_11.png

Рисунок 1.1.11 - Ткацкий станок с управлением с помощью перфокарт 61

_images/01_01_12.png

Рисунок 1.1.12 - Заполненная перфокарта конца XX века 62

К середине XIX века английский математик Чарлз Бэббидж разработал проект аналитической машины — прообраза современной ЭВМ (Рисунок 1.1.13).

_images/01_01_13.png

Рисунок 1.1.13 - Аналитическая машина Бэббиджа (первый механический общецелевой компьютер) в Музее естествознания (Лондон) 63

В аналитической машине Бэббидж предусмотрел следующие части:

  • склад (хранение данных и результатов обработки);

  • фабрика или мельница (производит операции над данными);

  • управляющий элемент (control);

  • устройства ввода‑вывода информации.

Для создания компьютера в современном понимании оставалось лишь придумать схему с хранимой программой, что было сделано 100 лет спустя в проекте ЭНИАК.

Коллега Бэббиджа Ада Лавлейс принимала участие в создании описания машины, составила первую в мире программу для этой машины (вычисление чисел Бернулли), а также ввела в употребление термины «цикл» и «рабочая ячейка», и считается первым программистом в истории.

В конце XIX века на основе идеи Беббиджа американский инженер Герман Холлерит создает первый табулятор - электромеханическую машину, предназначенную для автоматической обработки (суммирования и категоризации) числовой и буквенной информации, записанной на перфокартах, с выдачей результатов на бумажную ленту или специальные бланки (Рисунок 1.1.14).

_images/01_01_14.png

Рисунок 1.1.14 - Ранний табулятор фирмы IBM 64

1.1.3.3. Класс 3 - Произвольные задачи и данные

Идея хранение программы в памяти устройства начала зарождаться в 1936 г., когда Алан Тьюринг описал гипотетическую машину (названную им универсальной вычислительной машиной), известной сегодня как Машина Тьюринга. Машина имела бесконечное хранилище в виде ленты (память в современной терминологии), содержащее как данные, так и инструкции для манипулирования ими (в виде 0 и 1), а также имела простые инструкции для чтения/записи и перемещения этой ленты. Тезис Черча-Тьюринга гласил о том, что если какой‑либо процесс является вычисляемым, машина Тьюринга сможет его вычислить (быть запрограммирована для вычисления) 29.

Архитектура фон Неймана

Венгеро‑американский математик Джон фон Нейман, впечатленный работами Тьюринга, во время работы в Манхэттенском проекте был привлечен к работе над компьютером с хранимой в памяти программой. В это время он сформулировал идею архитектуры такого устройства, названной в последствии архитектурой фон Неймана, которая используется в виде базовой в большинстве современных ЭВМ (Рисунок 1.1.15).

_images/01_01_15.png

Рисунок 1.1.15 - Архитектура фон Неймана (одинарные линии показывают управляющие связи, двойные — информационные) 65

Основные положения:

  1. Компьютер состоит из нескольких основных устройств (арифметико‑логическое устройство, управляющее устройство, память, внешняя память, устройства ввода и вывода).

  2. Арифметико‑логическое устройство выполняет логические и арифметические действия, необходимые для переработки информации, хранящейся в памяти.

  3. Управляющее устройство обеспечивает управление и контроль всех устройств компьютера (управляющие сигналы указаны пунктирными стрелками).

  4. Инструкции (программы) и данные хранятся в одном и том же запоминающем устройстве и не должны быть «вшиты» в логику работы устройства.

  5. Данные, которые хранятся в запоминающем устройстве, представлены в двоичной форме.

  6. Память делится на ячейки одинакового размера (как правило, степень 2, например 8 бит), порядковый номер ячейки считается ее адресом.

Выполнение кода программы на компьютере с архитектурой фон Неймана определяет командный цикл (fetch-execute cycle) 30. Т.к. программа находится в памяти, а выполняет ее процессор 48, необходимо каждую инструкцию предварительно скопировать из памяти в память процессора (регистр). Адрес следующей команды сохраняется в процессоре в программном счетчике.

В простом виде командный цикл выглядит следующим образом:

инициализировать программный счетчик
бесконечный цикл
  получить команду, на которую указывает программный счетчик
  увеличить значение программного счетчика, чтобы он указывал на следующую команду
  декодировать команду
  выполнить команду
конец цикла

Этап декодирования необходим для определения, какое действие необходимо выполнить. Выполнение программы завершается при обнаружении команды остановки.

Одним из первых по‑настоящему современных компьютеров, реализующим архитектуру фон Неймана, был британский Манчестерский Марк I (1949 г.) - полностью электронный компьютер с хранимой в оперативной памяти программой (Рисунок 1.1.16). Аналогичные компьютеры (на собственной элементной базе) с разницей в несколько лет появились в дальнейшем в СССР, США и других странах.

_images/01_01_16.png

Рисунок 1.1.16 - Манчестерский Марк I 66

Марк I имел длину около 17 м., включал в себя 75 тысяч электронных ламп и выполнял операцию сложения за 3 с. (Видео 1.1.3).

Видео 1.1.3 - Машина Марк I

С тех пор совершенствовалась элементная база ЭВМ (изобретаются транзисторы, микропроцессоры и т.д.), компьютеры становились дешевле и доступнее массовому потребителю и спустя несколько десятилетий компьютер становится таким, каким мы знаем его сегодня.

1.1.3.4. Программирование на первых ЭВМ

До реализации компьютера на базе архитектуры фон Неймана решение задачи включало 3 отдельных этапа.

  1. Оператор вводил команду в вычислительное устройство напрямую в двоичном коде одним из способов:

    • через панель ввода: обычно это были тумблеры (кнопки переключения состояний) (Рисунок 1.1.17);

    • через устройство автоматического ввода: используя перфоленту или перфокарту (Рисунок 1.1.18).

    _images/01_01_17.png

    Рисунок 1.1.17 - Советский компьютер БЭСМ-2: ввод программы осуществлялся с помощью тумблерной панели 67

    _images/01_01_18.png

    Рисунок 1.1.18 - Британский Марк I: ввод программы осуществлялся с помощью перфоленты 68

  2. Команда распознавалась устройством и выполнялась им.

  3. Оператор снимал результаты выполнения команд и расшифровывал их на «человеческий» язык (Рисунок 1.1.19).

    _images/01_01_19.png

    Рисунок 1.1.19 - Советская МЭСМ и академик Лебедев С.А. 69

Схематично данный процесс выглядел так, как показано на Рисунке 1.1.20.

_images/01_01_20.png

Рисунок 1.1.20 - Схематичный процесс решения задачи на первых компьютерах

С ростом сложности вычислений увеличивалось количество деталей и расходных материалов устройства, поэтому очевидно, что таким способом можно было составить только небольшие программы.

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

Примечание

СССР внес огромный вклад в становление и развитие вычислительной техники, что признается во всем мире: Google: Remembering a remarkable Soviet computing pioneer, Советские компьютеры: преданные и забытые.

Рекомендуется дополнительно изучить историю вычислительной техники, например, на ресурсах 1, 2, 3 и др.

Обзор современного состояния отечественной IT-сферы и сферы микроэлектроники можно посмотреть на сайте Русский эксперт: Российские микропроцессоры, Российский_IT-сектор и др.

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

Язык программирования - формальная знаковая система, предназначенная для записи компьютерных программ.

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

От естественных языков язык программирования отличается тем, что предназначен для взаимодействия человека с ЭВМ, а не для общения людей между собой.

Язык программирования определяет набор правил:

  • лексических (словарный запас языка);

  • синтаксических (набор правил, описывающий комбинации символов алфавита, считающиеся правильно структурированной программой (документом) или ее фрагментом);

  • семантических (начальное смысловое значение операторов, основных конструкций языка и т.п.).

которые задают внешний вид программы и действия, которые выполнит исполнитель под ее управлением.

Как правило, язык программирования существует в нескольких, но существенно отличающихся видах:

  • стандарта языка: набора спецификаций, определяющих его синтаксис и семантику; стандарт языка может исторически развиваться;

  • воплощений (реализаций) стандарта: собственно программных средств, обеспечивающих работу согласно тому или иному варианту стандарта языка.

Например, язык С++ имеет официальный стандарт (ISO/IEC 14882:2014) и различные реализации: GNU C++, Microsoft Visual C++ и др.

1.1.4.1. Машинный код

Первым языком программирования можно считать Машинный код где каждая инструкция выполняет определенное действие:

  • операция с данными (например, сложение или копирование машинного слова в регистре или в памяти);

  • переход к другому участку кода (изменение порядка исполнения; переход может быть безусловным или условным, зависящим от результатов предыдущих инструкций)

при этом представляя несколько 0 и 1 в более удобном виде.

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

Пример одного из вариантов программы для вывода на экран фразы «Hello, world!» на машинном коде (в шестнадцатеричном и двоичном представлении) приведен в Листинге 1.1.1.

Листинг 1.1.1 - «Hello, world!» в машинном коде (в шестнадцатеричном и двоичном представлении) 74
BB 11 01 B9 0D 00 B4 0E 8A 07 43 CD 10 E2 F9 CD 20 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21

10111011 00010001 00000001 10111001 00001101 00000000 10110100 00001110 10001010 00000111
01000011 11001101 00010000 11100010 11111001 11001101 00100000 01001000 01100101 01101100
01101100 01101111 00101100 00100000 01010111 01101111 01110010 01101100 01100100 00100001

1.1.4.2. Языки ассемблера

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

Код на языке ассемблера в конечном итоге переводится в машинный код, используя специальную программу-преобразователь (транслятор), называемую ассемблером.

Программа из Листинга 1.1.1, записанная на языке ассемблера приведена в Листинге 1.1.2.

Листинг 1.1.2 - «Hello, world!» на языке ассемблера 74
1
2
3
4
5
6
7
8
9
XXXX:0100     mov     bx, 0111h       ; поместить в bx смещение строки HW
XXXX:0103     mov     cx, 000Dh       ; поместить в cx длину строки HW
XXXX:0106     mov     ah, 0Eh         ; поместить в ah номер функции прерывания 10h
XXXX:0108     mov     al, [bx]        ; поместить в al значение ячейки памяти, адрес которой находится в bx
XXXX:010A     inc     bx              ; перейти к следующему байту строки (увеличить смещение на 1)
XXXX:010B     int     10h             ; вызов прерывания 10h
XXXX:010D     loop    0108            ; если cx≠0, то уменьшить cx на 1 и перейти по адресу 0108
XXXX:010F     int     20h             ; прерывание 20h: завершить программу
XXXX:0111 HW  db      'Hello, World!' ; строка, которую требуется напечатать

Несомненным плюсом языков ассемблера по сегодняшний день является крайне эффективная работа программы (быстрый и компактный код).

В то же время поддержка подобной программы крайне трудоемка, код пишется для конкретного устройства, и ее перенос на другие устройства влечет за собой практически полное переписывание, что послужило причиной появления языков высокого уровня.

Примечание

Сегодня на языках ассемблера пишут программы или их фрагменты в тех случаях, когда критически важны:

  • быстродействие (драйверы, игры);

  • объем используемой памяти (загрузочные секторы, встраиваемое программное обеспечение, программы для микроконтроллеров и процессоров с ограниченными ресурсами, вирусы, программные защиты).

Участки кода на языке ассемблера также могут встраиваться в другие языки (например, C++) для оптимизации критичных участков кода.

1.1.4.3. 40-е гг.: первый язык высокого уровня

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

В скором времени начинает преобладать идея, что человек должен писать программы на более легком для него языке, чем машинные коды, а трудоемкий перевод в машинный код переложить на другую программу (транслятор), при этом транслятор также должен уметь в какой-либо степени делать перевод на машинный код различных устройств. Данная идея лежит в основе всех современных языков программирования.

Языки программирования, которые имеют достаточный уровень абстракции - оперируют сложными структурами данных и умеют выполнять над ними комплексные операции (что в машинном коде повлекло бы длинные и сложные цепочки кода), относят к языкам высокого уровня. Примеры таких языков - C, Pascal, Python, Java и др.

В общем случае целью создания новых языков программирования было упрощение написание программ и повышение уровня абстракции (от команд конкретной машины к языку человека).

На Рисунке 1.1.21 приведено дерево развития наиболее известных языков программирования по конец 2000-х гг. (рост идет и в настоящий момент). Еще один вариант дерева приведен тут 73.

_images/01_01_21.png

Рисунок 1.1.21 - Дерево наиболее известных языков программирования высокого уровня 4

На Видео 1.1.4 приведен краткий исторический обзор языков программирования (англ.).

Видео 1.1.4 - History Of Programming (Educational Video)

Исторически первым спроектированным языком программирования высокого уровня был Планкалкюль (нем. Plankalkül - исчисление планов), созданный немецким инженером Конрадом Цузе в 1943-45 году и впервые опубликованный в 1948 году.

Планкалкюль обладал многими возможностями, которыми обладают современные языки, однако, работа в отрыве от других специалистов Европы и США привела к тому, что лишь незначительная часть его работы стала известной, а сама разработка осталась теоретической. Полностью работа Цузе была издана лишь в 1972 году, а первая реализация языка Планкалкюль (для современных компьютеров) была создана в Свободном университете Берлина лишь в 2000 году, через пять лет после смерти Конрада Цузе.

1.1.4.4. 50-е гг.: сфера науки и бизнеса

В 50-е гг. в приоритете остаются задачи научного характера (математика, физика, искусственный интеллект). Программы на языках данного периода представляют собой последовательность команд, которые должен выполнить компьютер.

Fortran

В период 1954-1957 гг. американским ученым в области информатики Джоном Бэкусом совместно с компанией IBM разрабатывается Fortran (англ. FORmula TRANslator) - первый язык программирования общего назначения применяемый до сих пор (он совершенствуется и вбирает в себя различные нововведения, а последняя версия датируется 2010 г.), существует большое количество написанных на нем программ и библиотек подпрограмм.

Пример программы на одном из диалектов Фортрана приведен в Листинге 1.1.3.

Листинг 1.1.3 - Решение квадратного уравнения на Fortran 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
program Quadratic
  integer :: a, b, c
  real :: d, p1, p2
  complex :: cp2

  read (*, *), a
  if (a == 0) then
    write (*, *) "Not a quadratic equation"
    stop
  end if
  read (*, *) b
  read (*, *) c
  d = b * b - 4 * a * c
  p1 = - b / 2.0 / a
  if (abs(d) < 1.0e-9) then
    write (*, "(A, F8.3)") "x = ", p1
  elseif (d > 0) then
    p2 = sqrt(d) / 2.0 / a
    write (*, "(2(A, F8.3))") "x1 = ", p1 + p2, char(13) // char(10) // "x2 = ", p1 - p2
  else
    cp2 = sqrt(cmplx(d)) / 2.0 / a
    write (*, "(2(A, F8.3, F8.3), A)") "x1 = (", p1 + cp2, ")" // char(13) // char(10) // "x2 = (", p1 - cp2, ")"
  end if
end

Lisp

В 1958 г. американский информатик Джон Маккарти изобретает язык Lisp (англ. LISt Processing language) - первый язык программирования, который до сих пор является одним из основных средств моделирования различных аспектов искусственного интеллекта.

Нововведениями Лиспа являлись:

  • представление программ и данных системами линейных списков символов;

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

Пример программы на одном из диалектов Лиспа приведен в Листинге 1.1.4.

Листинг 1.1.4 - Решение квадратного уравнения на Lisp 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
(defun quadratic-roots-2 (A B C)
  (cond ((= A 0) (string "Not a quadratic equation."))
    (t
    (let ((D (- (* B B) (* 4 A C))))
      (cond ((= D 0) (concatenate 'string "x = " (write-to-string (/ (+ (- B) (sqrt D)) (* 2 A)))))
        (t
        (concatenate 'string (concatenate 'string "x1 = " (write-to-string (/ (+ (- B) (sqrt D)) (* 2 A))))
                             (concatenate 'string "~%x2 = " (write-to-string (/ (- (- B) (sqrt D)) (* 2 A)))))))))))

(let ((A (read))
     (B (read))
     (C (read)))
(format t (quadratic-roots-2 A B C)))

COBOL

В 1959 г. под руководством американской ученой и контр-адмирала флота США Грейс Хоппер создается язык COBOL (англ. COmmon Business Oriented Language), предназначенный, в первую очередь, для разработки бизнес-приложений.

Начиная карьеру как программист компьютера Марк I, Хоппер также вошла в историю как:

  • разработчик первого компилятора (транслятора, который преобразует высокоуровневый код в машинный код целевой машины) для компьютерного языка программирования;

  • сторонник и разработчик концепции машинно-независимых языков программирования;

  • популяризатор термина «отладка» (исправление сбоев в работе программы).

Кобол - стандартизованный язык практически с момента своего рождения, используемый и сегодня - еще в 2006 году Кобол считался языком программирования, на котором было написано больше всего строк кода.

Пример программы на одном из диалектов КОБОЛа приведен в Листинге 1.1.5.

Листинг 1.1.5 - Простой калькулятор (умножение и сложение) на COBOL 31
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
$ SET SOURCEFORMAT"FREE"
IDENTIFICATION DIVISION.
PROGRAM-ID.  Iteration-If.
AUTHOR.  Michael Coughlan.

DATA DIVISION.
WORKING-STORAGE SECTION.
01  Num1           PIC 9  VALUE ZEROS.
01  Num2           PIC 9  VALUE ZEROS.
01  Result         PIC 99 VALUE ZEROS.
01  Operator       PIC X  VALUE SPACE.

PROCEDURE DIVISION.
Calculator.
PERFORM 3 TIMES
 DISPLAY "Enter First Number      : " WITH NO ADVANCING
 ACCEPT Num1
 DISPLAY "Enter Second Number     : " WITH NO ADVANCING
 ACCEPT Num2
 DISPLAY "Enter operator (+ or *) : " WITH NO ADVANCING
 ACCEPT Operator
 IF Operator = "+" THEN
    ADD Num1, Num2 GIVING Result
 END-IF
 IF Operator = "*" THEN
    MULTIPLY Num1 BY Num2 GIVING Result
 END-IF
 DISPLAY "Result is = ", Result
END-PERFORM.
STOP RUN.

Algol

В 1958—1960 гг. появляется Algol (англ. ALGOrithmic Language) - язык, повлиявший практически на все языки следующего десятилетия (Pascal, С и другие). Алгол был популярен в Европе, в том числе в СССР, в то время как сравнимый с ним язык Фортран был распространен в США и Канаде. Алгол является предком довольно большого числа современных языков программирования (от Си и далее).

К нововведениям Алгола стоит отнести:

  • вложенные блоки: код мог быть сгруппирован в блоки (например, условие внутри условия) без необходимости вынесения кода в отдельную процедуру;

  • понятие области видимости: блок программы мог иметь свои закрытые переменные, процедуры и функции, невидимые для внешнего кода.

Пример программы на одном из диалектов Алгола (ALGOL 68) приведен в Листинге 1.1.6.

Листинг 1.1.6 - Решение квадратного уравнения на ALGOL 32
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
PROC print root = (INT ind, LONG COMPL x)VOID:
(   print(("x", ind, " := "));

    IF ABS(im OF x) < 1E-6 THEN
        print((re OF x, new line))
    ELSE print((x, new line))
    FI
);

main:
(   LONG COMPL a, b, c, d, x1, x2;

    print(("a := "));
    read((a));

    IF ABS a <1E-3 THEN
        print(( "Not a quadratic equation", new line));
        stop
    FI;

    print(("b := "));
    read((b));
    print(("c := "));
    read((c));

    a *:= 2;
    d := b*b-a*c*2.0;

    IF ABS d <1E-3 THEN
        print(("x := ", re OF (-b/a)))
    ELSE
        print root(1, (-b+long complex sqrt(d))/a);
        print root(2, (-b-long complex sqrt(d))/a)
    FI
)

1.1.4.5. 60-70-е гг.: универсальность

С повышением доступности компьютеров (например, в 1964 г. появляется популярная модель IBM 360) и появлением возможности работы в режиме разделения времени (time-sharing), доступ к компьютеру получили не только крупные научно-исследовательские центры, но и предприятия, образовательные учреждения, в том числе учащиеся и специалисты, не являющиеся подготовленными программистами, но нуждающиеся в решении на компьютере своих задач.

В связи с этим языки программирования продолжают совершенствоваться. В данный период также появляются основные парадигмы программирования, в рамках которых развиваются языки.

PL/I

В 1964 г. IBM разрабатывает язык PL/I (англ. Programming Language I), предназначавшийся для научных, инженерных и бизнес-ориентированных вычислений. В это время научные и бухгалтерские программы не только использовали разные компьютеры, но еще и писались на разных языках: научные — на Фортране, бухгалтерские — в основном на Коболе. Целью ПЛ/1 было создание языка, подходящего для обоих типов приложений.

Язык ввел в употребление множество нововведений, взятых на вооружение другими языками позже:

  • блочная структура;

  • большой набор встроенных типов данных;

  • мощный механизм итераций;

  • обработка исключительных ситуаций;

  • макросы и отладка.

Несмотря на заявленные характеристики и мощные возможности, PL/I не добился такого же успеха как Fortran или COBOL в виду сложной и неоптимальной для того времени реализации.

Пример программы на PL/I приведен в Листинге 1.1.7.

Листинг 1.1.7 - Пример программы на PL/I 4
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/* PL/I PROGRAM EXAMPLE
  INPUT: AN INTEGER, LISTLEN, WHERE LISTLEN IS LESS THAN
         100, FOLLOWED BY LISTLEN-INTEGER VALUES
 OUTPUT: THE NUMBER OF INPUT VALUES THAT ARE GREATER THAN
         THE AVERAGE OF ALL INPUT VALUES */

PLIEX: PROCEDURE OPTIONS (MAIN);
  DECLARE INTLIST (1:99) FIXED.
  DECLARE (LISTLEN, COUNTER, SUM, AVERAGE, RESULT) FIXED;
  SUM = 0;
  RESULT = 0;
  GET LIST (LISTLEN);
  IF (LISTLEN > 0) & (LISTLEN < 100) THEN2.9
    DO;
/* READ INPUT DATA INTO AN ARRAY AND COMPUTE THE SUM */
    DO COUNTER = 1 TO LISTLEN;
      GET LIST (INTLIST (COUNTER));
      SUM = SUM + INTLIST (COUNTER);
    END;
/* COMPUTE THE AVERAGE */
    AVERAGE = SUM / LISTLEN;
/* COUNT THE NUMBER OF VALUES THAT ARE > AVERAGE */
    DO COUNTER = 1 TO LISTLEN;
      IF INTLIST (COUNTER) > AVERAGE THEN
        RESULT = RESULT + 1;
    END;
/* PRINT RESULT */
    PUT SKIP LIST ('THE NUMBER OF VALUES > AVERAGE IS:');
    PUT LIST (RESULT);
    END;
  ELSE
    PUT SKIP LIST ('ERROR—INPUT LIST LENGTH IS ILLEGAL');
END PLIEX;

Basic

К 1964 г. появляется язык Basic (англ. Beginner’s All-purpose Symbolic Instruction Code — универсальный код символических инструкций для начинающих), создававшийся как инструмент, основной задачей которого было предоставить студентам-непрограммистам возможность после минимального обучения самостоятельно писать простейшие программы для собственных нужд, чтобы не отвлекать на эту работу специалистов. При этом подразумевалось, что на Бейсике должна быть возможность писать относительно эффективные программы, хоть и без знания принципов аппаратного обеспечения.

Несмотря на свою простоту Бейсик завоевал популярность и даже сегодня остается востребованным и используется в различных диалектах, например, в качестве встроенного языка текстового процессора Microsoft Word (VBA), или средства визуального программирования Visual Basic, а также других вариантах.

Пример программы на одном из диалектов Бейсика (QuickBASIC 4.5) приведен в Листинге 1.1.8.

Листинг 1.1.8 - Решение квадратного уравнения на Basic 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
PRINT "A = "
INPUT A
IF (A = 0) THEN
    PRINT "Not a quadratic equation."
ELSE
    PRINT "B = "
    INPUT B
    PRINT "C = "
    INPUT C
    D = B * B - 4 * A * C
    IF (D = 0) THEN
        PRINT "x = " + STR$(-B / 2! / A)
    ELSE
        IF (D > 0) THEN
            PRINT "x1 = " + STR$((-B + SQR(D)) / 2! / A)
            PRINT "x2 = " + STR$((-B - SQR(D)) / 2! / A)
        ELSE
            PRINT "x1 = (" + STR$(-B / 2! / A) + "," + STR$(SQR(-D) / 2! / A) + ")"
            PRINT "x2 = (" + STR$(-B / 2! / A) + "," + STR$(-SQR(-D) / 2! / A) + ")"
        END IF
    END IF
END IF

Pascal

В 1970 г. известный швейцарский ученый в области информатики Никлаус Вирт создает язык Pascal - один из наиболее известных языков программирования. Основной плюс языка как в то время, так и сейчас - баланс простоты/возможностей и привитие хорошего стиля программирования - до сих пор оставляет его популярным для обучения программированию и использования в ряде коммерческих приложений.

Несмотря на угасающую популярность, язык непрерывно развивается: сегодня существует множество диалектов, поддерживающих как визуальное и объектное программирование (Delphi или Lazarus/FreePascal), так и являющихся прямыми «улучшенными» потомками (Modula, Oberon и др.).

Пример программы на Паскале приведен в Листинге 1.1.9.

Листинг 1.1.9 - Решение квадратного уравнения на Pascal 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
program Quadratic;

var
   A,B,C,D: integer;

begin
   write('A = ');
   readln(A);
   if (A=0) then
   begin
      writeln('Not a quadratic equation.');
      halt;
   end;
   write('B = ');
   readln(B);
   write('C = ');
   readln(C);
   D := B*B-4*A*C;
   if (D=0) then
   begin
      writeln('x = ',-B/2.0/A);
      halt;
   end;
   if (D>0) then
   begin
      writeln('x1 = ',(-B+Sqrt(D))/2.0/A);
      writeln('x2 = ',(-B-Sqrt(D))/2.0/A);
   end
   else
   begin
      writeln('x1 = (',-B/2.0/A,',',Sqrt(-D)/2.0/A,')');
      writeln('x2 = (',-B/2.0/A,',',-Sqrt(-D)/2.0/A,')');
   end;
end.

Prolog

В 1972 г. появляется первый язык логического программирования Prolog, основанный на теории и аппарате математической логики.

Пример программы на одном из диалектов Пролога (GNU Prolog) приведен в Листинге 1.1.10.

Листинг 1.1.10 - Решение квадратного уравнения на Prolog 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
q :- write('A = '),
     read(A),
     (   A = 0, write('Not a quadratic equation');
         write('B = '),
         read(B),
         write('C = '),
         read(C),
         D is B*B-4*A*C,
         (   D = 0, write('x = '), X is -B/2/A, write(X);
             D > 0, write('x1 = '), X1 is (-B+sqrt(D))/2/A, write(X1), nl, write('x2 = '), X2 is (-B-sqrt(D))/2/A, write(X2);
             R is -B/2/A, I is abs(sqrt(-D)/2/A),
             write('x1 = ('), write(R), write(', '), write(I), write(')'), nl,
             write('x1 = ('), write(R), write(', -'), write(I), write(')')
         )
     ).

Smalltalk

В 1972 г. в научно-исследовательской компании Xerox PARC американский ученый в области теории вычислительных систем Алан Кэй с коллегами разрабатывает первый объектно-ориентированный язык общего назначения Smalltalk.

Smalltalk привнес следующие нововведения:

  • все — объекты: строки, целые числа, логические значения, определения классов, блоки кода и т.д.;

  • работа программы - изменение свойств объекта и вызов действий, которые они поддерживают;

  • динамическая типизация: типы переменных не указываются в программе, а является ли операция правильной, определяет объект-получатель;

  • автоматическая сборка мусора;

  • выполнение кода в виртуальной машине: программы Smalltalk обычно компилируются в байткоды и выполняются виртуальной машиной, что позволяет выполнять их на любом оборудовании, для которого существует виртуальная машина (то, что сегодня делает Java).

Пример программы на одном из диалектов Smalltalk приведен в Листинге 1.1.11.

Листинг 1.1.11 - Класс-оценка на Smalltalk 33
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
"   CpSc 428 - Example: Grades class  (file grades.st)"

"  A grade, which is implemented as an instance of class Grade, is"
"  a pair of integers (score, weight), representing 'score' points"
"  out of a total of 'weight' possible points.  "

Object subclass: #Grade
   instanceVariableNames: 'score weight'
   classVariableNames: ''
   poolDictionaries: ''
   category: 'grades' !

!Grade class methodsFor: 'instance creation' !

score: s weight: w

  " Create a new instance of a Grade with score s and weight w."

  | newGrade |

  newGrade := super new.
  newGrade score: s weight: w.
  ^newGrade
! !

!Grade methodsFor: 'initialization' !

score: s weight: w

   "Set the score and weight values for a grade."

   score := s.
   weight := w
! !

!Grade methodsFor: 'accessing' !

score

  ^score
!

weight

  ^weight
! !

C

В период с 1969 по 1973 г. сотрудники американской телекоммуникационной компании Bell Labs Деннис Ритчи и Кен Томпсон разрабатывают язык C - язык общего назначения, изначально предназначенный для реализации операционной системы UNIX.

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

Пример программы на Си приведен в Листинге 1.1.12.

Листинг 1.1.12 - Решение квадратного уравнения на C 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <math.h>
#include <stdio.h>

int main()
{
  int A, B, C, D;
  printf("A = ");
  scanf("%d", &A);
  if (A == 0) {
    printf("Not a quadratic equation.\n");
    return 0;
  }

  printf("B = ");
  scanf("%d", &B);
  printf("C = ");
  scanf("%d", &C);

  D = B * B - 4 * A * C;
  if (D == 0) {
    printf("x = %f\n", -B / 2.0 / A);
    return 0;
  }

  if (D > 0) {
    printf("x1 = %f\nx2 = %f\n",
           (-B + sqrt(D)) / 2.0 / A, (-B - sqrt(D))/ 2.0 / A);
  } else {
    printf("x1 = (%f, %f)\nx2 = (%f, %f)\n",
           -B / 2.0 / A, sqrt(-D) / 2.0 / A, -B / 2.0 / A, -sqrt(-D) / 2.0 /A);
  }
  return 0;
}

Ada

Ada - язык, разрабатываемый в течение 70-х гг. Министерством обороны США с целью разработать единый язык программирования для встроенных систем (бортовых систем управления военными объектами - кораблями, самолетами, танками, ракетами, снарядами и т.п.), функционирующих в режиме реального времени.

Синтаксис Ады унаследован от языков типа Algol или Паскаль, но расширен, а также сделан более строгим и логичным. Для удовлетворения требованиям надежности язык построен таким образом, чтобы как можно большее количество ошибок обнаруживалось на этапе компиляции. Кроме того, одним из требований при разработке языка была максимально легкая читаемость текстов программ, даже в ущерб легкости написания. Язык используется в том числе отечественными военными (на нем, например, написана станция документальной связи МО РФ), однако в целом малопопулярен.

Пример программы на Ada приведен в Листинге 1.1.13.

Листинг 1.1.13 - Решение квадратного уравнения на Ada 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
with Ada.Text_IO,
     Ada.Integer_Text_IO,
     Ada.Float_Text_IO,
     Ada.Numerics.Elementary_Functions,
     Ada.Text_IO.Complex_IO,
     Ada.Numerics.Generic_Complex_Types,
     Ada.Numerics.Generic_Complex_Elementary_Functions;
use Ada.Text_IO, Ada.Integer_Text_IO, Ada.Float_Text_IO;

procedure QuadraticEquation is
    package Complex_Types is new Ada.Numerics.Generic_Complex_Types (Float);
    package Complex_Functions is new Ada.Numerics.Generic_Complex_Elementary_Functions(Complex_Types);
    package Complex_IO is new Ada.Text_IO.Complex_IO (Complex_Types);

    use Complex_Types, Complex_Functions, Complex_IO;

    A,B,C,D: Integer;
    A2f, Bf, S: Float;
    Dc: Complex;
begin
    Put("A = ");
    Get(Item => A);
    if A = 0 then
        Put_Line("Not a quadratic equation.");
        return;
    end if;
    Put("B = ");
    Get(B);
    Put("C = ");
    Get(C);
    A2f := Float(2*A);
    Bf := Float(B);

    D := B*B-4*A*C;
    if D = 0 then
        Put("x = ");
        Put(-Bf/A2f);
    elsif D > 0 then
        S := Ada.Numerics.Elementary_Functions.Sqrt(Float(D));
        Put("x1 = ");
        Put((-Bf+S)/A2f);
        Put_Line("");
        Put("x2 = ");
        Put((-Bf-S)/A2f);
    else
        Dc := Compose_From_Cartesian (Re => Float(D), Im => 0.0);
        Put("x1 = ");
        Put((-Bf+Complex_Functions.Sqrt(Dc))/A2f);
        Put_Line("");
        Put("x2 = ");
        Put((-Bf-Complex_Functions.Sqrt(Dc))/A2f);
    end if;
end QuadraticEquation;

1.1.4.6. 80-е гг.: консолидация идей и модульность

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

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

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

C++

В 1983 г. программист компании Bell Бьерн Страуструп представляет язык C++ - первый язык, совместивший черты высокоуровневого языка (объектно-ориентированного, в частности), и низкоуровнего.

C++ широко используется для разработки программного обеспечения, являясь одним из самых популярных языков программирования. Область его применения включает создание операционных систем, разнообразных прикладных программ, драйверов устройств, приложений для встраиваемых систем, высокопроизводительных серверов, а также развлекательных приложений. Имеет компиляторы практически под все популярные платформы и операционные системы. Сегодня также позволяет создавать приложения с графическим интерфейсом (Microsoft Visual C++, С++Qt и др.).

Оказав огромное влияние на более современные языки Java и C#, язык постоянно развивается и представляет собой собранную воедино большую массу технологий. Последний стандарт языка, известный как C++14, датируется 2014 г.

Пример программы на C++ приведен в Листинге 1.1.14.

Листинг 1.1.14 - Пример описания классов «Транспортное средство» и его потомков на C++ 34
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class Vehicle {
 public:
     explicit
     Vehicle( int topSpeed )
     : m_topSpeed( topSpeed )
     {}
     int TopSpeed() const {
        return m_topSpeed;
     }

     virtual void Save( std::ostream& ) const = 0;

 private:
     int m_topSpeed;
 };

 class WheeledLandVehicle : public Vehicle {
 public:
     WheeledLandVehicle( int topSpeed, int numberOfWheels )
     : Vehicle( topSpeed ), m_numberOfWheels( numberOfWheels )
     {}
     int NumberOfWheels() const {
       return m_numberOfWheels;
     }

     void Save( std::ostream& ) const; // is implicitly virtual

 private:
     int m_numberOfWheels;
 };

 class TrackedLandVehicle : public Vehicle {
 public:
    TrackedLandVehicle ( int topSpeed, int numberOfTracks )
    : Vehicle( topSpeed ), m_numberOfTracks ( numberOfTracks )
    {}
    int NumberOfTracks() const {
       return m_numberOfTracks;
    }
    void Save( std::ostream& ) const; // is implicitly virtual

  private:
    int m_numberOfTracks;
  };

Objective-C

В то же время 1983 г. в компании Apple под руководством Брэда Кокса разрабатывается собственный Си с классами – Objective-C, построенный на основе языка Си и идей Smalltalk.

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

Пример программы на Objective-C приведен в Листинге 1.1.15.

Листинг 1.1.15 - Вычисление объема с использованием классов на Objective-C 35
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#import <Foundation/Foundation.h>

@interface Box:NSObject
{
    double length;   // Length of a box
    double breadth;  // Breadth of a box
    double height;   // Height of a box
}
@property(nonatomic, readwrite) double height; // Property

-(double) volume;

@end

@implementation Box

@synthesize height;

-(id)init
{
   self = [super init];
   length = 1.0;
   breadth = 1.0;
   return self;
}

-(double) volume
{
   return length*breadth*height;
}

@end

int main( )
{
   NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   Box *box1 = [[Box alloc]init];    // Create box1 object of type Box
   Box *box2 = [[Box alloc]init];    // Create box2 object of type Box

   double volume = 0.0;     // Store the volume of a box here

   // box 1 specification
   box1.height = 5.0;

   // box 2 specification
   box2.height = 10.0;

   // volume of box 1
   volume = [box1 volume];
   NSLog(@"Volume of Box1 : %f", volume);
   // volume of box 2
   volume = [box2 volume];
   NSLog(@"Volume of Box2 : %f", volume);
   [pool drain];
   return 0;
}

Eiffel

В 1986 г. французский ученый в области информатики Бертран Мейер создает язык Eiffel (Эйфель) — объектно-ориентированный язык программирования с алголоподобным синтаксисом, в котором впервые был реализован метод контрактного программирования.

Метод контрактного программирования предполагает, что проектировщик должен определить формальные, точные и верифицируемые спецификации интерфейсов для компонентов системы. Данные спецификации называются «контрактами» в соответствии с концептуальной метафорой условий и ответственности в гражданско-правовых договорах.

Eiffel используется в серьезных разработках, от которых зависят жизни людей: в аэрокосмической отрасли, в банковско-финансовой сфере и др. Несмотря на это язык слабораспространен, т.к. компиляторы с Eiffel от автора языка дороги и не так распространены, как компиляторы C/C++, что, в свое время, и ограничило распространение этого языка, а свободных/бесплатных альтернатив долгое время не было.

Пример программы на Eiffel приведен в Листинге 1.1.16.

Листинг 1.1.16 - Описание класса «Банковский счет» на Eiffel 36
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
note
    description: "Простые банковские счета"

class
    ACCOUNT

create
     make

feature {NONE} -- Инициализация
     make -- Инициализировать
          do
               create all_deposits
          end

feature -- Доступ
     balance: INTEGER
              -- Текущий баланс

     deposit_count: INTEGER
              -- Количество сделанных взносов с момента открытия
         do
                   Result := all_deposits.count
         end
feature -- Изменение элемента
    deposit (sum: INTEGER)
              -- Добавить `sum' на счет.
         require
                 non_negative: sum >= 0
         do
              all_deposits.extend (sum)
              balance := balance + sum
             ensure
              one_more_deposit: deposit_count = old deposit_count + 1
              updated: balance = old balance + sum
         end

feature {NONE} -- Реализация
    all_deposits: DEPOSIT_LIST
              -- Список взносов с момента открытия счета

invariant
    consistent_balance: balance = all_deposits.total
    zero_if_no_deposits: all_deposits.is_empty implies (balance = 0)
end -- класс ACCOUNT

Perl

Ларри Уолл, лингвист по образованию, в 1987 г. создает язык Perl (англ. Practical Extraction and Report Language - «практический язык для извлечения данных и составления отчетов») - язык программирования общего назначения, который был первоначально создан для манипуляций с текстом, но на данный момент используется для выполнения широкого спектра задач, включая системное администрирование, веб-разработку, сетевое программирование, игры, биоинформатику, разработку графических пользовательских интерфейсов. Язык можно охарактеризовать скорее как практичный (легкость в использовании, эффективность, полнота), чем красивый (элегантность, минималистичность).

Пример программы на Perl приведен в Листинге 1.1.17.

Листинг 1.1.17 - Программа выполняет замену в строке на основе конфигурационного файла 37
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/local/bin/perl

use English;
use Carp;
use Getopt::Long;

open(D, $opt_def) || die "can't open definition file:$opt_def\n";
while (<D>) {
    ($oldp, $newp) = split;
    $dic{$oldp}=$newp;
}
close(D);

$oldStr = "";
$newStr = "";
while (<STDIN>) {
    $oldStr = $_;
    foreach $k (keys %dic) {
      s/$k/$dic{$k}/g;
    }

    $newStr = $_;
    if ($oldStr ne $newStr) {
      print STDERR "\n";
      print STDERR "old>>$oldStr";
      print STDERR "new>>$newStr";
    }
    print;
}

Tcl

В 1988 г. американский ученый в области информатики Джон Оустерхаут создает язык Tcl (англ. Tool Command Language - «командный язык инструментов») - один из первых скриптовых языков высокого уровня. Основная область применения - быстрое прототипирование, создание графических интерфейсов для консольных программ (пакетов программ), встраивание в прикладные программы, тестирование. Также Tcl применяется в веб-разработке.

Пример программы на Tcl приведен в Листинге 1.1.18.

Листинг 1.1.18 - Генерация простых чисел и сохранение в файл на Tcl 38
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
proc all_primes {max} {
    set primes [list 2]
    for {set test 3} {$test <= $max} {incr test 2} {
        set maxTest [expr {int(sqrt($test))}]
        foreach prime $primes {
            if {$prime  > $maxTest} {
                lappend primes $test
                break
            }
            if {![expr {$test % $prime}]} {
               break
            }
        }
    }
    return $primes
}

proc all_primes_run {} {
    puts -nonewline "Compute all primes below:  "
    flush stdout
    set max [gets stdin]
    if {$max < 2} {
        set max 2
    }
    set primes [all_primes $max]

    set f [open "primes_below_$max" w]
    puts $f $primes
    close $f
}

1.1.4.7. 90-е гг.: Интернет-эпоха

90-е годы характеризовались распространением сети Интернет и персональных компьютеров, а также увеличением количества данных, что послужило очередным толчком для дальнейшего развития языков программирования. Многие языки, созданные в это время, являются свободными (пользователи имеют права на неограниченную установку, запуск, свободное использование, изучение, распространение и изменение (совершенствование), а также распространение копий и результатов изменения), что также явилось фактором широкого распространения ряда языков.

Можно выделить несколько тенденций и идей развития в это время:

  • продолжение комбинации идей предыдущих десятилетий и распространение функциональных языков;

  • повышение продуктивности разработки;

  • продолжение развития скриптовых (динамических) языков;

  • графический интерфейс пользователя (ГПИ, англ. Graphical User Interface, GUI).

Желание увеличить производительность работы программиста в совокупности с сохранением проверенных временем идей привело к появлению новых языков высокого уровня, а также сред быстрой разработки (англ. Rapid Application Development - RAD), включающих кроме самого языка и транслятора интегрированную среду разработки (англ. Integrated Development Environment - IDE). Все такие языки программирования были объектно-ориентированными, а в ряде случаев IDE также позволяла выполнять графическое проектирование приложений.

Python

В 1991 г. нидерландский программист Гвидо ван Россум представляет Python — высокоуровневый мультипарадигменный язык программирования общего назначения, ориентированный на повышение производительности разработчика и читаемости кода. Синтаксис ядра Python минималистичен, в то же время стандартная библиотека включает большой объем полезных функций.

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

Пример программы на Python приведен в Листинге 1.1.19.

Листинг 1.1.19 - Решение квадратного уравнения на Python 3 39
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import math

print("Введите коэффициенты для квадратного уравнения (ax^2 + bx + c = 0):")
a = float(input("a = "))
b = float(input("b = "))
c = float(input("c = "))

discr = b**2 - 4 * a * c;
print("Дискриминант D = %.2f" % discr)
if discr > 0:
	x1 = (-b + math.sqrt(discr)) / (2 * a)
	x2 = (-b - math.sqrt(discr)) / (2 * a)
	print("x1 = %.2f \nx2 = %.2f" % (x1, x2))
elif discr == 0:
	x = -b / (2 * a)
	print("x = %.2f" % x)
else:
	print("Корней нет")

Ruby

Спустя 2 года, в 1993 г., японский разработчик Юкихиро Мацумото создает язык Ruby - высокоуровневый язык программирования для быстрого и удобного объектно-ориентированного программирования, который, по словам автора, более мощный, чем Perl, и более объектно-ориентированный, чем Python.

Ruby имеет немало оригинальных решений, редко или вообще не встречающихся в распространенных языках программирования - расширенная работа с массивами, классами и т.д.

Основные сферы применения приблизительно такие же, как и у Python.

Пример программы на Ruby приведен в Листинге 1.1.20.

Листинг 1.1.20 - Объявление класса на Ruby 40
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class Person < Object       # объявление класса начинается с ключевого слова class, за которым
                            # следует имя, класс Person наследуется от Object
  include Comparable        # подмешиваются к классу методы экземпляра
  mix MyModel               # подмешивание без наложения имен
  extend MyModel            # методы класса
                            # и добавляет методы <, <=, ==, >=, > и between?
                            # с использованием нижеопределённого
                            # в классе <=>
                            #
  @variable                 # переменная экземпляра
  @@count_obj = 0           # переменная класса для подсчёта числа созданных объектов
                            #
                            # конструктор для создания объектов с помощью new
  def initialize(name, age) # name, age - параметры метода
                            # название переменных объекта начинается с @
    @name, @age = name, age # создаём объекты и увеличиваем счётчик на 1
    @@count_obj += 1
  end

  def <=>(person)           # переопределение оператора <=>
                            # (это даёт возможность использовать метод sort)
    @age <=> person.age     # из метода возвращается последнее вычисленное выражение,
  end

  def to_s                  # для форматированного вывода информации puts
    "#{@name} (#{@age})"    # конструкция #{x} в 2-х кавычках замещается в Ruby значением x
  end

  def inspect               # похож на to_s, но используется для диагностического вывода
    "<#{@@count_obj}:#{to_s}>"
  end
                            # пример метапрограммирования: добавляет методы для доступа к
                            # переменным объекта
  attr_reader :name, :age
end
                            # создаём массив объектов
group = [ Person.new("John", 20),
          Person.new("Markus", 63),
          Person.new("Ash", 16) ]
                     # => [<3:John (20)>, <3:Markus (63)>, <3:Ash (16)>]
                     # здесь при работе с irb автоматически вызывается метод inspect
                     # вызываем методы массива сортировка и разворачивание его в обратном порядке
puts group.sort.reverse # Печатает:
                        # Markus (63)
                        # John (20)
                        # Ash (16)
                                   # обращаемся к функции, которая была добавлена
                                   # автоматически (используя <=>) при включении Comparable
group[0].between?(group[2], group[1]) # => true

Lua

Еще один скриптовый язык программирования Lua в 1993 г. в Бразилии разрабатывает преподаватель университета Роберто Иерусалимский совместно с коллегами.

Язык широко используется для создания тиражируемого программного обеспечения (например, на нем написан графический интерфейс пакета Adobe Lightroom). Также получил известность как язык программирования уровней и расширений во многих играх (в том числе World of Warcraft) из-за удобства встраивания, скорости исполнения кода и легкости обучения.

Пример программы на Lua приведен в Листинге 1.1.21.

Листинг 1.1.21 - Решение квадратного уравнения на Lua 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
local A = io.read('*n')
if A==0 then
    io.write('Not a quadratic equation.')
    return
end

local B = io.read('*n')
local C = io.read('*n')
D = B*B-4*A*C
if D==0 then
    io.write('x = ', -B/2/A)
else if D>0 then
        io.write('x1 = ', (-B+math.sqrt(D))/2/A, '\nx2 = ', (-B-math.sqrt(D))/2/A)
     else
        io.write('x1 = (', -B/2/A, ',', math.sqrt(-D)/2/A, ')\nx2 = (', -B/2/A, ',', -math.sqrt(-D)/2/A, ')\n')
     end
end

R

В 1993 г. также создается R - язык программирования для статистической обработки данных и работы с графикой. R широко используется как программное обеспечение для анализа данных и фактически стал стандартом для статистических программ, имеет собственные IDE.

Пример программы на R приведен в Листинге 1.1.22.

Листинг 1.1.22 - Ведомость оценок на R 77
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# В переменную a поместить список всех оценок:
a <- c(4,3,3,3,3,4,4,4,4,4,5,4,4,4,5,5,5,5,+
3,5,5,4,4,3,3,4,4,3,5,5,4,3,3,4,4,3,3,5,4,5,5)

# В переменную n поместить количество оценок:
length(a) -> n

# Средний балл:
m <- mean(a)

# Таблица (горизонтальная) с подсчётом количества оценок:
t <- table(a)

# Преобразование в более удобный формат данных (вертикальную таблицу):
f <- as.data.frame(t)

# Вычисление процентной доли и запись её в третий столбец:
mapply(function(r) r*100/n, f[,2]) -> f[,3]

# Заголовки столбцов:
colnames(f) <- c("Оценка", "Кол-во", "%")

# Вывод результатов:
a
n
m
f

# Результат
# [1] 4 3 3 3 3 4 4 4 4 4 5 4 4 4 5 5 5 5 3 5 5 4 4 3 3 4 4 3 5 5 4 3 3 4 4 3 3 5
# [39] 4 5 5
# [1] 41
# [1] 4
#   Оценка Кол-во        %
# 1      3     12 29.26829
# 2      4     17 41.46341111
# 3      5     12 29.26829

JavaScript

В 1995 г. набирает популярность язык JavaScript как встраиваемый язык для программного доступа к объектам приложений. Наиболее широко применяется в браузерах как язык сценариев для придания интерактивности веб-страницам.

Пример программы на JavaScript приведен в Листинге 1.1.23.

Листинг 1.1.23 - Пример кода Javascript на HTML-странице 41
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<p>Image Rollover:</p>
<script type="text/javascript">
<!--
// Pre load images for rollover
if (document.images) {
	smile = new Image
	nosmile = new Image

	smile.src = "http://www.quackit.com/pix/smile.gif"
	nosmile.src = "http://www.quackit.com/pix/nosmile.gif"
}


function swapImage(thisImage,newImage) {
	if (document.images) {
		document[thisImage].src = eval(newImage + ".src")
	}
}
-->
</script>
<a href="http://www.quackit.com/javascript/image_rollovers.cfm"
onMouseOver="swapImage('jack','smile')"
onMouseOut="swapImage('jack','nosmile')">
<img src="http://www.quackit.com/pix/nosmile.gif"
	width="100"
	height="100"
	border="0"
	alt="Picture of Jack"
	name="jack">
</a>
<div class="more-info">
<p>More info: <a href="/javascript/image_rollovers.cfm">Image Rollovers</a></p>
</div>

PHP

В 1995 г. появляется PHP (англ. PHP: Hypertext Preprocessor — «PHP: препроцессор гипертекста») — скриптовый язык общего назначения, интенсивно применяемый для разработки веб-приложений. В настоящее время поддерживается подавляющим большинством хостинг-провайдеров и является одним из лидеров среди языков, применяющихся для создания динамических веб-сайтов.

Пример программы на PHP приведен в Листинге 1.1.24.

Листинг 1.1.24 - Пример кода PHP на HTML-странице для отправки почты 42
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<html>
  <head>
  <title>Simple Send Mail Form</title>
  </head>
  <body>
  <h1>Mail Form</h1>
  <form name="form1" method="post" action="SimpleEmail.php">
  <table>
      <tr><td><b>To</b></td><td><input type="text" name="mailto" size="35"></td></tr>
      <tr><td><b>Subject</b></td>
          <td><input type="text" name="mailsubject" size="35"></td></tr>
      <tr><td><b>Message</b></td>
          <td><textarea name="mailbody" cols="50" rows="7"></textarea></td>
      </tr>
      <tr><td colspan="2">
            <input type="submit" name="Submit" value="Send">
          </td>
      </tr>
   </table>
 </form>
 </body>
 </html>


<!-- SimpleEmail.php
  <?php
    if (empty ($mailto) ) {
       die ( "Recipient is blank! ") ;
    }

    if (empty ($mailsubject) ){
       $mailsubject=" " ;
    }

    if (empty ($mailbody) ) {
       $mailbody=" " ;
    }

    $result = mail ($mailto, $mailsubject, $mailbody) ;

    if ($result) {
       echo "Email sent successfully!" ;
    }else{
       echo "Email could not be sent." ;
    }
?>
-->

Java

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

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

Java-технологии используются в огромном количестве устройств (более 3 млрд.), используется как в качестве разработки настольных и мобильных приложений, так и веб-приложений; кроме того, существует множество сред визуальной разработки, поддерживающих язык Java.

Пример программы на Java приведен в Листинге 1.1.25.

Листинг 1.1.25 - Расчет площади треугольника на Java 43
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
 * @author: BeginnersBook.com
 * @description: Program to Calculate area of Triangle in Java
 * with user interaction. Program will prompt user to enter the
 * base width and height of the triangle.
 */
import java.util.Scanner;
class AreaTriangleDemo {
   public static void main(String args[]) {
      Scanner scanner = new Scanner(System.in);

      System.out.println("Enter the width of the Triangle:");
      double base = scanner.nextDouble();

      System.out.println("Enter the height of the Triangle:");
      double height = scanner.nextDouble();

      //Area = (width*height)/2
      double area = (base* height)/2;
      System.out.println("Area of Triangle is: " + area);
   }
}

GUI

Распространенность персональных компьютеров и мобильных устройств привело к необходимости разработки приложений, удобных для использования неподготовленным человеком - для чего необходим был графический интерфейс. Многие из языков данного периода, включая более старые языки, получили возможность создания приложений с графическим интерфейсом.

На Рисунке 1.1.22 приведен пример IDE Delphi (Object Pascal), аналогичной средой, но для языка Basic выступал Visual Basic (1991), в качестве одного из вариантов для C++ выступала графическая библиотека Qt (Рисунок 1.1.23).

_images/01_01_22.png

Рисунок 1.1.22 - IDE Borland Delphi 1 (1995 г.) 70

_images/01_01_23.png

Рисунок 1.1.23 - IDE Qt Creator 71

1.1.4.8. 2000-е и текущие тренды

Развитие языков продолжилось в 2000-е гг. и идет до сих пор. Некоторые тренды:

  • увеличение поддержки функционального программирования в ключевых языках программирования для упрощения кода;

  • введение конструкций для поддержки параллельного программирования (несколько процессов) и распределенных вычислений (несколько компьютеров);

  • механизмы увеличения безопасности языка (проверки типов, зависимостей и т.д.);

  • альтернативные механизмы для композиции и модульности: примеси, делегаты, аспектно-ориентированное программирование и др.

  • компонентно-ориентированная разработка (в т.ч. использование различных фреймворков);

  • метапрограммирование;

  • предметно-ориентированные языки;

  • автоматизация процесса программирования (XML for graphical interface (XUL, XAML));

  • кроссплатформенность;

  • интеграция с базами данных;

  • открытое программное обеспечение как философия создания и развития языков программирования;

  • исследования возможности разработки языков программирования для квантовых компьютеров.

Наиболее известные языки данного периода:

C# и .NET Framework

В 2000 г. корпорация Майкрософт под руководством Андерса Хейлсберга представляет язык C# - объектно-ориентированный язык программирования для специально созданной платформы Microsoft .NET Framework, основной идеей которой являлось обеспечение свободы разработчика за счет предоставления ему возможности создавать приложения различных типов, способные выполняться на различных типах устройств и в различных средах.

Общая схема работы языков в рамках платформы .NET приведена на Рисунке 1.1.24.

_images/01_01_24.png

Рисунок 1.1.24 - Принцип работы языков платформы .NET 72

C# относится к семье языков с C-подобным синтаксисом, из них его синтаксис наиболее близок к C++ и Java. В языке представлены практически все современные достижения «языкостроения», а реализация языка доступна в том числе на не-Windows средах (проект Mono).

Пример программы на C# приведен в Листинге 1.1.26.

Листинг 1.1.26 - Hello world на C# (консольное приложение) 47
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// A Hello World! program in C#.
using System;
namespace HelloWorld
{
    class Hello
    {
        static void Main()
        {
            Console.WriteLine("Hello World!");

            // Keep the console window open in debug mode.
            Console.WriteLine("Press any key to exit.");
            Console.ReadKey();
        }
    }
}

Go

Go - компилируемый, многопоточный язык программирования, разработанный компанией Google в 2009 г. Первоначальная разработка Go началась в сентябре 2007 года, а его непосредственным проектированием занимались Роберт Гризмер, Роб Пайк и Кен Томпсон.

На данный момент его поддержка осуществляется для операционных систем: FreeBSD, OpenBSD, Linux, Mac OS X, Windows, начиная с версии 1.3 в язык Go включена экспериментальная поддержка DragonFly BSD, Plan 9 и Solaris, начиная с версии 1.4 поддержка платформы Android.

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

Пример программы на Go приведен в Листинге 1.1.27.

Листинг 1.1.27 - Цикл for в Go (единственная циклическая конструкция!) 49
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// `for` is Go's only looping construct. Here are
// three basic types of `for` loops.

package main

import "fmt"

func main() {

    // The most basic type, with a single condition.
    i := 1
    for i <= 3 {
        fmt.Println(i)
        i = i + 1
    }

    // A classic initial/condition/after `for` loop.
    for j := 7; j <= 9; j++ {
        fmt.Println(j)
    }

    // `for` without a condition will loop repeatedly
    // until you `break` out of the loop or `return` from
    // the enclosing function.
    for {
        fmt.Println("loop")
        break
    }
}

Rust

Rust (англ. Rust - ржавчина) - мультипарадигменнй компилируемый язык программирования общего назначения, спонсируемый Mozilla Research, поддерживающий функциональное программирование, модель акторов (один из подходов к распараллеливанию программ, где одновременно выполняющиеся процессы передают друг другу сообщения), процедурное программирование, объектно-ориентированное программирование.

Rust - системный язык программирования, внимание которого сосредоточено на трех задачах: безопасность, скорость и параллелизм. Он сопоставим по скорости и возможностям с C++, однако, дает большую безопасность при работе с памятью, что обеспечивается механизмами ограничения. Rust также направлен на достижение «абстракции с нулевой стоимостью».

После нескольких лет активной разработки первая стабильная версия (1.0) вышла 15 мая 2015 года, после чего новые версии выходят раз в 6 недель. Программы, написанные на ранних стабильных версиях языка будут собираться и на более новых стабильных версиях.

Пример программы на Rust приведен в Листинге 1.1.28.

Листинг 1.1.28 - Вложенные циклы в Rust 50
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#![allow(unreachable_code)]

fn main() {
    'outer: loop {
        println!("Entered the outer loop");

        'inner: loop {
            println!("Entered the inner loop");

            // This would break only the inner loop
            //break;

            // This breaks the outer loop
            break 'outer;
        }

        println!("This point will never be reached");
    }

    println!("Exited the outer loop");
}

1.1.5. Классификация языков программирования

Языки программирования классифицируются по различным категориям, рассмотрим их основные группы.

Примечание

Более обширную классификацию см. в Википедии: Programming language classification.

1.1.5.1. Низкоуровневые и высокоуровневые языки

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

Языки программирования, которые имеют достаточный уровень абстракции - оперируют сложными структурами данных и умеют выполнять над ними комплексные операции (что в машинном коде повлекло бы длинные и сложные цепочки кода), относят к языкам высокого уровня. Примеры таких языков - C, Pascal, Python, Java и др.

1.1.5.2. Трансляторы: компиляторы, интерпретаторы и гибриды

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

Программа, предназначенная для перевода кода с языка программирования в машинный код называется транслятором. На сегодняшний день выделяется 3 типа трансляторов: компиляторы, интерпретаторы и гибриды.

  1. Компиляторы однократно осуществляют перевод всего кода в машинный код. Результатом процесса компиляции является исполняемый модуль (например, EXE-файл для ОС Windows).

  2. Интерпретаторы анализируют и тут же выполняют программу покомандно, по мере поступления ее исходного кода на вход интерпретатора.

    Схематично сравнительная работа компилятора и интерпретатора приведена на Рисунке 1.1.25.

    _images/01_01_25.png

    Рисунок 1.1.25 - Сравнительная схема работы компилятора и интерпретатора

    Каждый из вариантов имеет свои плюсы и минусы (Таблица 1.1.2).

    Таблица 1.1.2 - Преимущества и недостатки компиляторов и интерпретаторов

    Характеристика

    Компилятор

    Интерпретатор

    1

    Быстродействие

    (+) Обеспечивают максимальную производительность

    (-) Дополнительный слой интерпретатора замедляет выполнение программы и может требовать больше ресурсов

    2

    Переносимость

    (-) Исполняемый файл привязан к платформе компиляции

    (+) Программа может быть легко перенесена на другую платформу, для которой имеется интерпретатор

  3. Гибриды пытаются совместить плюсы компиляторов и интерпретаторов. Наиболее известные представители - язык Java и платформа .NET Framework.

Практически все современные языки относительно «размывают» границы данной классификации и в той или иной степени являются гибридными.

1.1.5.3. Типизация

Языки высокого уровня работают не с битами и байтами, а с более абстрактными структурами данных - типами, поэтому эти языки принято считать типизированными.

Выделяют несколько видов типизации 44 45:

  1. Явная / неявная.

  2. Статическая / динамическая.

  3. Сильная (строгая) / слабая (нестрогая).

1.1.5.3.1. Явная / неявная

1. Явная: тип новых переменных, функций и их аргументов необходимо задавать явно.

Примеры: C++, Pascal, C#.

var
  a: Integer; // Явно указываем, что a - целое число

...

  a := 5; // Pascal

2. Неявная: языки с неявной типизацией перекладывают эту задачу на компилятор / интерпретатор

Примеры: PHP, Python, JavaScript.

a = 5  # Python - определит, что это целое число во время выполнения

1.1.5.3.2. Статическая / динамическая

1. Статическая: конечные типы переменных и функций устанавливаются на этапе компиляции.

Примеры: C, Java, C#.

2. Динамическая: все типы выясняются во время выполнения программы.

Примеры: Python, JavaScript.

Понятия «статический» или «динамический» язык программирования подразумевают данный вид типизации.

1.1.5.3.3. Сильная / слабая

1. Сильная (строгая): не позволяет смешивать в выражениях различные типы и не выполняет автоматические неявные преобразования

Примеры: Java, Python.

a = 5
b = a + "строка"  # Ошибка в Python

2. Слабая (нестрогая): множество неявных преобразований происходит автоматически, даже если может произойти потеря точности или преобразование неоднозначно.

Примеры: C, JavaScript, Visual Basic, PHP.

a = 5
b = a + "строка" ' Visual Basic (5 преобразуется в строку и результат равен "5строка")

Все виды типизации пересекаются, например, язык C имеет [явную, статическую, слабую] типизацию, а язык Python — [неявную, динамическую, сильную].

1.1.5.4. Парадигмы программирования

За время своего развития языки программирования создавались под влиянием определенных идей, которые определяли возможности языка и стиль написания программ. Совокупность таких идей и понятий называется парадигмой программирования.

Выделяют 4 парадигмы программирования:

  1. Императивная (процедурная).

  2. Функциональная.

  3. Логическая.

  4. Объектно-ориентированная.

Языки программирования могут поддерживать одну или несколько парадигм и, соответственно, называться императивными, объектно-ориентированными и т.д.

1. Императивная (процедурная).

Наиболее известная парадигма.

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

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

-- НАЧАЛО --

определить, хватит ли в чайнике воды для заваривания чая
ЕСЛИ воды мало:
  - открыть кран с водой
  - налить воды в чайник
  - закрыть кран с водой
подключить чайник к сети
включить чайник
ПОКА вода греется:
  - прочитать новость в Интернете
  - посмотреть в окно

-- КОНЕЦ --

2. Функциональная.

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

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

3. Логическая.

Программа рассматривается как множество логических формул: аксиом (фактов и правил), описывающих свойства некоторых объектов, и теоремы, которые необходимо доказать.

Выполнение программы – доказательство теоремы, в ходе которого строится объект с описанными свойствами.

4. Объектно-ориентированная.

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

Объект содержит некоторые данные (свойства, состояние объекта) и операции над этими данными (методы), описывающие поведение объекта. Классы представляют шаблоны объектов со схожей структурой и схожим поведением. Обычно описание классов имеет иерархическую структуру.

Выполнение объектно-ориентированной программы представляет собой обмен сообщениями между объектами, в результате которого они меняют свои состояния.

-- НАЧАЛО --

-- описание объектов --

Чайник
  Свойства
    - объем_налитой_воды
  Методы
    - достаточно_воды_для_заваривания_чая? (да/нет)
    - закипел? (да/нет)
    - подключить_к_сети(Розетка)
    - включить

Кран
  Методы
    - открыть
    - закрыть

Человек
  Методы
    - прочитать_новость_в_Интернете
    - посмотреть_в_окно
    - посмотреть_уровень_воды_в_чайнике(Чайник)

Розетка
  Свойства
    - свободна?
  Методы
    - освободить

-- основной алгоритм --

Чайник1 = Чайник()
Человек1 = Человек()
Кран1 = Кран()
Розетка1 = Розетка()

ЕСЛИ НЕ Чайник1.достаточно_воды_для_заваривания_чая?
  Кран1.открыть
  ПОКА НЕ Чайник1.достаточно_воды_для_заваривания_чая?
    Человек1.посмотреть_уровень_воды_в_чайнике(Чайник1)
  Кран1.закрыть

ЕСЛИ Розетка1.свободна?
  Розетка1.освободить
Чайник1.подключить_к_сети(Розетка1)
Чайник1.включить

ПОКА НЕ Чайник1.закипел?
  Человек1.прочитать_новость_в_Интернете
  Человек1.посмотреть_в_окно

-- КОНЕЦ --

1.1.6. Выбор языка программирования

Выбор языка программирования для выполнения какого-либо проекта - ответственное дело и зависит от многих факторов.

Примечание

Следует отметить, что все языки высокого уровня общего назначения обладают полнотой по Тьюрингу, т.е. на них можно реализовать любую вычислимую функцию. С практической точки зрения это означает, что программа на одном тьюринг-полном языке программирования может быть записана на другом тьюринг-полном языке программирования, что делает «пустыми» «священные войны» в стиле «на языке X это сделать можно, а на языке Y нельзя», однако, несомненно, некоторые языки позволяют решить ту или иную задачу эффективнее.

1.1.6.1. Экосистема

Одной из наиболее важных представляется экосистема языка программирования, в которую обычно входят:

1. Средства разработки (IDE).

Позволяет удобно и эффективно писать, и отлаживать код.

2. Библиотеки и Фреймворки.

Расширяют базовые возможности языка (графический интерфейс, тестирование, сетевое программирование, графика и т.д.).

3. Системы пакетирования и развертывания.

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

4. Сообщество (коммьюнити).

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

1.1.6.2. Применимость (нишевость)

Многие из языков программирования создавались для более эффективного решения задач конкретного класса. В связи с этим, в индустрии разработки ПО сложились определенные тренды, какие языки и в какой области применять более целесообразно (Рисунок 1.1.26).

_images/01_01_26.png

Рисунок 1.1.26 - Комплексный рейтинг популярности с указанием их типовой применимости по данным IEEE (Институт инженеров электротехники и электроники) 76

Тип

Описание

Web

ПО для Веб

Mobile

ПО для мобильных устройств

Enterprise

Настольное ПО (десктопное)

Embedded

Системное ПО

1.1.6.3. Популярность

В мире существуют различные рейтинги для определения популярности языков. Популярность влияет на распространенность языка, вероятность найти помощь в интернете, наличие необходимых библиотек и т.д. (Рисунок 1.1.27, 1.1.28)

_images/01_01_27.png

Рисунок 1.1.27 - Самые популярные языки программирования в мире в разные годы по Индексу TIOBE 75

_images/01_01_28.png

Рисунок 1.1.28 - Исторический рейтинг языков программирования в мире по Индексу TIOBE 75

Примечание

Главное правило - выбирать язык под задачу, с учетом сформировавшегося опыта индустрии и команды!


4(1,2)

Sebesta, W.S Concepts of Programming languages. 10E; ISBN 978-0133943023.

5

Python - официальный сайт. URL: https://www.python.org/.

6

Python - FAQ. URL: https://docs.python.org/3/faq/programming.html.

7

Саммерфилд М. Программирование на Python 3. Подробное руководство. — М.: Символ-Плюс, 2009. — 608 с.: ISBN: 978-5-93286-161-5.

8

Лучано Рамальо. Python. К вершинам мастерства. — М.: ДМК Пресс , 2016. — 768 с.: ISBN: 978-5-97060-384-0, 978-1-491-94600-8.

9

Лучшие профессии и специальности: топ-50. URL: https://edunews.ru/professii/rating/top-50.html.

27

Зарплаты айтишников в первом полугодии 2022. URL: https://habr.com/ru/article/679698/.

28

Обязательно ознакомьтесь с интересной историей развития вычислительной техники более подробно. URL: https://ru.wikipedia.org/wiki/История_вычислительной_техники.

29

09 - Введение в алгоритмы. Машина Тьюринга. URL: https://youtu.be/s7R8HXpgiHA.

30

Instruction cycle. URL: https://en.wikipedia.org/wiki/Instruction_cycle.

31

COBOL Example Programs. URL: http://www.csis.ul.ie/cobol/examples/.

32

CODE MUSEUM - Algol60. URL: http://www.gribbleshnibit.com/projects/ProgrammingLanguagesSite/languages/algol68/.

33

CpSc 428 - Example: Grades class. URL: https://people.cs.clemson.edu/~turner/courses/cs428/current/examples/smalltalk/st/grades.html.

34

C++ Programming/Classes/Abstract Classes. URL: https://en.wikibooks.org/wiki/C%2B%2B_Programming/Classes/Abstract_Classes.

35

Objective-C Classes & Objects. URL: http://www.tutorialspoint.com/objective_c/objective_c_classes_objects.htm.

36

Русскоязычный перевод документации Eiffel по технологии проектирования по контракту. URL: https://www.opennet.ru/base/dev/DesignByContract.txt.html.

37

Perl Scripts. URL: https://ru.scribd.com/document/186880415/Perl-Scripts.

38

Sample Math Programs. URL: http://wiki.tcl.tk/951.

39

Найти корни квадратного уравнения (Python). URL: http://younglinux.info/python/task/quadratic.

40

Объявление класса на Ruby. URL: https://ru.wikipedia.org/wiki/Ruby.

41

JavaScript Examples. URL: http://www.quackit.com/javascript/examples/.

42

PHP/Form/Form based Email. URL: http://wbex.ru/index.php/PHP/Form/Form_based_Email.

43

Java program to calculate area of Triangle. URL: http://beginnersbook.com/2014/01/java-program-to-calculate-area-of-triangle/.

44

Система типов. URL: https://ru.wikipedia.org/wiki/Система_типов.

45

Ликбез по типизации в языках программирования. URL: https://habrahabr.ru/post/161205/.

46

Google - Remembering a remarkable Soviet computing pioneer. URL: https://googleblog.blogspot.ru/2011/12/remembering-remarkable-soviet-computing.html.

47

Hello World – Создаем первую программу (Руководство по программированию на C#). URL: https://msdn.microsoft.com/ru-ru/library/k1sx6ed2.aspx.

48

Из чего состоит процессор. URL: https://begenovsoft.wordpress.com/.

49

Go by Example: For. URL: https://gobyexample.com/for.

50

Rust: Nesting and labels. URL: http://rustbyexample.com/flow_control/loop/nested.html.

51

Кабина СУ-35. URL: http://ic.pics.livejournal.com/fyodor_photo/45977679/332874/332874_original.jpg.

52

Кабина СУ-35. URL: https://tengrinews.kz/userdata/news/2017/news_318044/photo_215084.jpg.

53

Сбербанк Онлайн. URL: http://www.sberbank.ru/portalserver/content/atom/contentRepository/content/1.jpg?id=040273b4-a2c9-401d-9685-301fbf1423c1.

54

Классификация программного обеспечения. URL: https://upload.wikimedia.org/wikipedia/ru/3/31/GeneralizedLayeredComputerStructure_syssoft.png.

55

Схема компьютерной системы. URL: https://upload.wikimedia.org/wikipedia/commons/5/5f/Operating_system_placement-ru.svg.

56

Agile team: roles and responsibilities. URL: http://aoteastudios.com/files/agile-roles-responsibilities-poster.pdf.

57

Паскалина. URL: https://upload.wikimedia.org/wikipedia/commons/8/80/Arts_et_Metiers_Pascaline_dsc03869.jpg.

58

Арифмометр «Феликс». URL: https://upload.wikimedia.org/wikipedia/commons/6/6d/Felix_kurskiy.jpg.

59

Логарифмическая линейка. URL: https://upload.wikimedia.org/wikipedia/commons/2/27/Sliderule_2005.jpg.

60

Turing Bombe. URL: http://aoteastudios.com/files/agile-roles-responsibilities-poster.pdf.

61

Ткацкий станок с управлением с помощью перфокарт. URL: https://htstatic.imgsmail.ru/pic_original/7c5fa00b81ae69d26e395b65585fa629/96184/.

62

Заполненная перфокарта конца XX века. URL: https://upload.wikimedia.org/wikipedia/commons/8/8d/Перфокарта.jpg.

63

Аналитическая машина Бэббиджа. URL: https://upload.wikimedia.org/wikipedia/commons/a/ac/AnalyticalMachine_Babbage_London.jpg.

64

Ранний табулятор фирмы IBM. URL: https://upload.wikimedia.org/wikipedia/commons/d/d5/Lochkarte_1.jpg.

65

Архитектура фон Неймана. URL: http://sdo.uspi.ru/mathem&inform/lek_10/Image231.gif.

66

Манчестерский Марк I. URL: https://upload.wikimedia.org/wikipedia/ru/d/d8/Manchester_Mark2.jpg.

67

Советский компьютер БЭСМ-2. URL: http://chernykh.net/images/stories/lang/besm2.jpg.

68

Британский Марк I. URL: http://chernykh.net/images/stories/food/mk03.jpg.

69

Советская МЭСМ. URL: http://istrasvvt.narod.ru/img/img/MESM.jpg.

70

IDE Borland Delphi 1. URL: http://www.webdelphi.ru/wp-content/uploads/2011/09/delphi1.png.

71

IDE Qt Creator. URL: https://support.criticallink.com/redmine/attachments/download/6188.

72

Принцип работы языков платформы .NET. URL: http://www.intuit.ru/EDI/24_01_16_3/1453587871-3663/tutorial/381/objects/1/files/01_03.png.

73

History of Programming Languages. URL: https://omohundro.files.wordpress.com/2010/01/prog_lang_poster-1.pdf.

74(1,2)

Программа «Hello, world!». URL: https://ru.wikipedia.org/wiki/Машинный_код#.D0.9F.D1.80.D0.BE.D0.B3.D1.80.D0.B0.D0.BC.D0.BC.D0.B0_.C2.ABHello.2C_world.21.C2.BB

75(1,2)

TIOBE Index. URL: http://www.tiobe.com/tiobe-index/.

76

Interactive: The Top Programming Languages. URL: https://spectrum.ieee.org/top-programming-languages/.

77(1,2,3,4,5,6,7,8,9)

progopedia - Квадратное уравнение. URL: http://progopedia.ru/example/quadratic-equation/.