История циклична и программирование не является исключением. Все прекрасно знают, что программирование является постоянно развивающейся сферой. Ежедневно мы пользуемся продуктами программистов, такими как мобильные приложения, игры, веб-сайты, социальные сети и многое другое. Без программ, компьютеры были бы просто набором железа.
Профессия программиста является одной из самых динамично развивающихся. Для поддержания компетентности необходимо постоянно следить за новыми технологиями, библиотеками, фреймворками и другими инструментами, необходимыми в профессии программиста. Но в этой статье предлагаю перевернуть карту и проследовать от началу пути.
Хронология развития программирования позволяет оценить интенсивность появления новых информационных продуктов в этой сфере.
Первые программисты и машинный код
Первые программисты были истинными ценителями своего дела. Они разговаривали с компьютером на его языке, который называется "машинный код". Этот язык представляет собой последовательность из двух символов - 0 и 1. Каждый компьютер работает на электричестве, поэтому он понимает, что ток есть - это 1, а его отсутствие - 0. Синтаксис машинного кода очень простой, но использование его требует хороших навыков, много практики и большого объема знаний. Перевод мыслей с человеческого языка в машинный код приходилось делать самостоятельно, так как у первых программистов не было переводчика под рукой.
Сложности использования машинного кода
Сложность использования машинного кода заключается в том, что он использует только две цифры - 0 и 1, в отличие от десятичной системы счисления, где мы привыкли использовать цифры от 0 до 9. Для перевода чисел в двоичный код существуют различные способы. Например, для перевода числа 9 в двоичный код можно использовать метод последовательного умножения на 2 и записи остатков в столбике.
- В первой строке справа налево записываются все числа, начиная от 1 с последующим их умножением на 2.
- Во второй строке движение происходит наоборот слева направо, в столбике под необходимым числом ставится 1, а под теми, которые не понадобятся, ставится 0.
Этот метод позволяет перевести число 9 в двоичный код.
Складываются из первой строчки числа 8+1=9, в итоге цифры из второй строки 1001 и есть двоичный код привычного нам числа 9. А как же тогда буквы?
Как мы уже знаем, компьютер знает только 0 и 1, значит, буквы должны быть представлены как числа с порядковой нумерацией. Следовательно, нумерация осуществляется в привычной нам десятичной системе счисления, выглядит это как таблица. Первая таблица появилась немного позже первых вычислительных машин и называлась ASCII7, вот ее вид:
Видно, что первые английские буквы начинались с номера 101 - А, как выглядит число 101 в двоичном коде? Вот так: 1100101. Давайте посмотрим, как будет выглядеть в двоичном коде текст “Hello world”:
11011101001000110011010100110101010011110011101101000101001101010010000.
Ну что, есть желание попереписываться?
Из этого кода сразу становится понятно, какая же была интересная и многообразная жизнь у программистов прошлого. Но через время программисты собрали волю в кулак и создали первый язык программирования под названием “Assembler”, который позволяет писать “человекопонятные” команды.
Развитие Assembler
Когда речь идет о Assembler как о языке с определенным синтаксисом, важно понимать, что это понятие включает в себя различные диалекты. Развитие Assembler в первую очередь произошло не в программной индустрии, а в области "железа". Вместо лампочек и реле, в которых можно было сказать: включить ток (1) или отключить (0), появились вшитые команды внутри самого процессора. Это позволило программистам использовать команды процессора для совершаемых действий.
Все команды, предоставляемые процессором, позволяют программисту взаимодействовать с его памятью. Память процессора является самой быстрой частью в компьютере, а второй по скорости является ОЗУ (оперативное запоминающее устройство), также известное как "оперативка".
В первое время у каждого процессора был свой набор команд из-за разнообразия задач, для которых они создавались. Однако со временем количество процессоров на рынке стало сокращаться, и появились наиболее популярные варианты синтаксиса, такие как Intel-синтаксис и AT&T-синтаксис.
Команды Assembler включают в себя операции перемещения данных, арифметические операции (сложение, вычитание, умножение, деление) и работу с портами ввода-вывода (например, клавиатура как ввод и наушники как вывод).
Хотя после машинного кода все может показаться проще, при решении конкретных задач необходимо учитывать как набор команд конкретного процессора, так и операционную систему.
Разработка программ на Assembler может быть сложной из-за технических нюансов, но существуют методы, позволяющие обойти эти преграды. Однако стоит задуматься о том, а используется ли сейчас данный язык?
Да, современный ассемблер используется для написания драйверов. Драйверы представляют собой специальный набор инструкций, который указывает операционной системе, как взаимодействовать с устройствами. Можно провести аналогию, что операционная система подобна водителю автомобиля, а драйверы - это информация на ручке переключения передач, указателях на ручке поворотников и т.д. Современный ассемблер используется именно для этой цели, так как он работает ближе всего к "железу" и позволяет "говорить" на его языке.
Однако с развитием индустрии программного обеспечения и увеличением сложности задач становится достаточно сложно для программистов писать крупные проекты на ассемблере. Это также увеличивает сроки разработки программ и их стоимость. В связи с этим возникает вопрос о дальнейшем использовании ассемблера в разработке программного обеспечения.
Что появилось позже?
Появление первого высокоуровневого машиннонезависимого языка программирования Fortran произошло позже. Этот язык не зависит от конкретного процессора, и программисту просто нужно писать код на синтаксисе Fortran, а компилятор выполнит остальную работу. Компилятор - это программа, которая считывает код, написанный на языке высокого уровня (например, Fortran), и переводит его на язык Assembler. Хотя при использовании компилятора теряется скорость выполнения программ, современные компиляторы становятся достаточно умными и способны оптимизировать код настолько эффективно, что программисты не могут достичь такой производительности, если будут писать программы на чистом Assembler. Однако на небольших проектах написание программ на чистом Assembler может привести к более высокой производительности.
С появлением высокоуровневых языков программирования у программистов появилась возможность писать более человекоподобные наборы команд и операторов. Также появились функции с готовыми решениями для арифметических задач, работы со строками и других задач. Важным моментом стало появление первых структур данных, таких как массивы. В высокоуровневых языках программирования появилась возможность хранить данные не только по одному значению, но и целыми массивами, что значительно улучшило возможности программистов. Также стало возможным разбивать программы на подпрограммы и использовать удобные инструменты для повышения эффективности работы
Как появлялись высокоуровневые языки?
Fortran
Первым высокоуровневым языком, который появился, был Fortran. Он был создан в компании IBM с целью облегчить написание программистам и избавить их от необходимости писать программы на Assembler. В начале идея высокоуровневого языка встретилась с негативной реакцией, так как программы на Fortran исполнялись медленнее, чем на Assembler. Однако со временем Fortran стал невероятно популярным, подобно тому, как мобильные телефоны стали неотъемлемой частью нашей жизни, несмотря на первоначальные сомнения в их ценности. Программа, печатающая сообщение "Hello, World!" на языке Fortran, выглядит следующим образом:
ALGOL
Следующим языком, который появился, был ALGOL. Он разрабатывался с целью разнообразить языковое пространство и устранить монополию языка Fortran. В Америке ALGOL не смог стать конкурентом для Fortran, но успешно прижился в научной сфере Европы и СССР. Поскольку у ALGOL было несколько диалектов, программы на нем могли выглядеть по-разному. Традиционное "Hello, World!" на одном из диалектов выглядит так:
LISP
В мире программирования структура данных "массив" дала сильный толчок, но в 1960 году появился язык LISP, который работает со списками вместо массивов и является первым языком с динамической памятью и автоматической очисткой мусора.
Разница между массивом и списком заключается в том, что при создании массива программист указывает точное количество ячеек в оперативной памяти, в то время как в списках нет необходимости указывать требуемое количество ячеек. Списки позволяют добавлять или удалять ячейки по мере необходимости, используя динамическую память, что приводит к появлению мусора, который периодически нужно убирать.
Можно проиллюстрировать разницу между массивом и списком на примере кинотеатра. Массив подобен кинотеатру в торговом центре с фиксированным количеством посадочных мест, где кресла жестко прикреплены к полу. Список же подобен кинотеатру под открытым небом, где количество мест зависит от количества посетителей, и посадочные места могут динамически расширяться и сокращаться.
Язык LISP использует принцип работы памяти, а сообщение "Hello, World" на нем выглядит следующим образом:
Этот язык до сих пор используется программистами благодаря своему приятному синтаксису и удобству.
Pascal
Далее пропустим несколько малоизвестных языков программирования, погибших смертью храбрых в боях жесткой конкуренции за место в сердцах программистов, и подойдем к языку Pascal.
Язык Pascal является отличным представителем, отражающим стиль программирования времен его создания. Он отличается строгой типизацией при объявлении переменных и процедурным подходом, который предполагает отделение каждой части программы на процедуры. Когда необходимо выполнить определенный участок программы, вызывается соответствующая процедура. Изначально создатель языка стремился сделать его идеальным для стандарта программирования. Однако со временем стандарты изменились, и язык, пытаясь следовать им, получил ряд диалектов.
Сегодня язык Pascal можно встретить практически во всех школах на уроках информатики. Считается, что он позволяет лучше всего раскрыть "истинный путь" к программированию для учеников. Однако его синтаксис является немного устаревшим, поэтому встретить его где-то, кроме образовательных учреждений, достаточно трудно. Тем не менее, все еще существуют компании, в которых когда-то разрабатывали программное обеспечение на одном из диалектов данного языка. Поддержка на Pascal может встречаться из-за затратной процедуры переписывания на другой язык. Намеки на данный язык можно увидеть в объявлениях при приеме на работу, но это большая редкость.
У Pascal есть динамическая память, но она достаточно условная. Фактически язык был бы очень удобным, если бы не был морально устаревшим. Традиционное сообщение на данном языке выводится посредством следующего кода:
Си
Следующий разработанный язык программирования - основа большинства вещей, которыми мы пользуемся повседневно. Речь идет о С ("си"). Язык С разрабатывался специально для создания операционной системы UNIX. Основная идея заключалась в сохранении производительности исполняемых программ, близкой к скорости Assembler, при этом позволяя программисту писать обычный код, привычный для высокоуровневых языков программирования. Операционная система Linux написана на языке С, и этот язык нашел применение практически во всех сферах, став отцом для многих современных языков, таких как C++, C#, Java и даже JavaScript. Создатель языка JavaScript вдохновлялся синтаксисом С при создании нового языка. Несмотря на сходство в названиях, JavaScript и Java - абсолютно разные языки программирования. Вернемся к языку С. Он располагает специальным типом данных, структурой, отсюда появилась парадигма программирования "Структурное программирование". Традиционное сообщение на языке С выводится так:
На этом с развитием высокоуровневых языков можно остановиться и перейти к новому витку развития: парадигмам.
Появление парадигм
Парадигма программирования - это стиль написания программ. Один из примеров - императивная парадигма, где программист пишет последовательность команд для выполнения процессором, подобно командам в армии между командиром и солдатом. Язык Assembler относится к этой парадигме.
Другой пример - структурное программирование, где задача разбивается на составные части, подобно организации сотрудников в структурные подразделения для решения конкретных задач. Язык С включает в себя структуры данных, и из этой парадигмы появилась "структура" в языке.
Третий пример - объектно-ориентированное программирование (ООП), подобное созданию проекта автомобиля на автомобильном заводе. Проект описывает все детали, а рабочие занимаются только своей деталью. В языке появляется новая структура данных под названием "Класс", который описывает программист, и из него создаются объекты, занимающие место в памяти компьютера.
Объектно-ориентированное программирование на сегодняшний день является наиболее популярной парадигмой в разработке крупных проектов, таких как игры. Оно позволяет программистам думать об архитектуре своей программы, не задумываясь об устройстве компьютера.
Появление мультипарадигмальных языков
В 1983 году появился язык программирования с названием "C++". Этот язык добавил возможность работы с классами (ООП) к языку С, что сделало его одним из лидеров в мире программирования. Множество программ, включая браузеры и игровые движки, написаны на C++. Язык постоянно дополняется новыми функциями и конструкциями, и его использование проникает во все сферы человеческой деятельности. Название языка обусловлено добавлением к С дополнительных возможностей, а оператор "++" в языке С используется для увеличения значения на единицу. Программа, выводящая сообщение "Hello World", будет выглядеть следующим образом:
В 1991 году появился язык программирования Python, который предлагает максимально упростить чтение программы и использовать небольшое количество операторов языка. Весь язык Python состоит из объектов, даже создавая переменную для хранения числа, в памяти компьютера создается объект. Этот подход позволяет работать с любым типом хранимых данных, например, списками, которые позволяют выполнять различные операции, такие как сортировка, поиск элементов и другие. Python применяет синтаксис вложенности, где для выделения блока программы достаточно поставить 4 пробела или нажать один раз на клавишу Tab. Это позволило повысить производительность программиста, и данный язык уже долгое время занимает лидирующие позиции в списке Top-10 языков программирования. Например, для вывода сообщения "Hello World" достаточно использовать следующий код: print("Hello World"). Python является очень лаконичным языком.
В 1995 году появился язык программирования Java, который был создан с учетом необходимости кроссплатформенности. Кроссплатформенность означает, что программы, написанные на одном языке, могут работать на различных операционных системах, таких как Windows, Linux, MacOS, Android и других. Например, программы на С++ требуют компиляции под конкретную операционную систему, а Python использует интерпретатор для чтения программы при каждом запуске. Однако Java использует систему перевода программы в специальный байт-код в процессе компиляции, который понимает виртуальная Java-машина. Это позволяет запускать программы на любой операционной системе без дополнительных сложностей. Java синтаксически похож на С++, и его основным преимуществом является кроссплатформенность. Для вывода традиционного сообщения "Hello World" требуется небольшой объем кода, но производительность Java может быть ниже, чем у некоторых других языков.
В 1995 году возникла необходимость в создании интерактивных приложений внутри веб-страниц. В это время страницы в браузере были статичными, и не поддерживали интерактивность, такую как создание модальных окон, обработка форм ввода данных и другие возможности. Этот язык, который мы сегодня знаем как JavaScript, был разработан для решения этой проблемы. JavaScript быстро развивается и используется не только в браузере, но также на сервере для генерации и отправки страниц. Благодаря быстрому развитию JavaScript, сайты стремятся к одностраничности, чтобы предоставлять полноценные динамические интерфейсы без перезагрузки страницы. Для отображения стандартного сообщения "Hello World" в браузере можно использовать следующий код, который был доступен в языке в 1995 году: alert("Hello World");. Этот код вызывает всплывающее окно с сообщением "Hello World".
Рейтинг языков
Для получения статистики использования языков программирования достаточно обратиться к ресурсу, где собраны исходные коды, написанные программистами в рабочих проектах. Один из таких ресурсов - GitHub. Здесь программисты демонстрируют свои работы для портфолио или предоставляют готовые решения для использования другими разработчиками. GitHub позволяет отслеживать изменения в коде без необходимости создания копий всего проекта при каждом изменении.
Статистика рейтинга языков GitHub за прошедший 2020 год:
- Python;
- Java;
- Javascript;
- C#;
- Cи и C++;
- PHP;
- R;
- Objective-C;
- Swift;
- MATLAB.
Как видите, много знакомых нам языков занимают лидирующие позиции. Эта статистика с каждым годом вносит новые языки в этот список, но Python, JavaScript, Java, C и С++ находятся здесь уже длительное время.
А как Вы считаете, благодаря чему языки программирования оказываются в этом списке? Благодаря тому, что у них подходящие характеристики для определенных задач программистов? Отчасти да, но в большей мере стоит понимать, что чистый (нативный) язык в промышленной разработке используют очень редко. Популяризация языка происходит благодаря его экосистеме.
Появление фреймворков
Экосистема языка программирования включает в себя множество компонентов. Одним из ключевых элементов являются библиотеки, которые позволяют разработчикам легко подключать готовые функции и классы для использования в своих проектах, экономя время на написании собственных решений.
Однако библиотеки представляют лишь часть помощи, доступной разработчику. Основным инструментом для быстрой разработки больших проектов являются фреймворки. Фреймворк, переводимый с английского как "каркас", предоставляет разработчику готовую структуру и набор модулей, таких как система аутентификации, модули для работы с базой данных, шаблонизаторы и маршрутизаторы, необходимые для удобной и эффективной разработки проекта.
Если разработчик пытается создать все эти компоненты с нуля на чистом языке программирования, это может значительно затянуть процесс разработки и привести к утрате актуальности проекта на рынке. Фреймворки предоставляют готовый каркас, включающий все необходимые модули, объединенные в единую логическую структуру. Разработчику остается лишь установить фреймворк, создать проект и начать писать код.
Однако стоит отметить, что фреймворки не предназначены для выполнения функций, которые предоставляют обычные библиотеки конкретного языка программирования. Фреймворк предоставляет свой собственный синтаксис, сфокусированный на упрощении разработки конкретного типа проекта.
Хотя фреймворки написаны на конкретном языке программирования, разработчик в процессе использования фреймворка использует этот язык. Однако основная задача фреймворка заключается в предоставлении удобного набора инструментов, включая собственный синтаксис, для работы над проектом.
Несмотря на наличие готовых фреймворков, знание нативного языка программирования остается важным. Программист, обладающий глубокими знаниями нативного языка, востребован на рынке труда, так как способен решать разнообразные задачи, включая работу с фреймворками.
Сфера программирования постоянно развивается, и появление новых фреймворков или обновление существующих требует от программистов постоянного обучения и адаптации. Постоянное изучение новых решений делает программиста настоящим специалистом, готовым к решению различных задач.
Что планируется в перспективе?
Вряд ли найдется человек, который сможет сделать прогноз на будущее. Вспомните программистов на Assembler, которые и не предполагали появление таких удобных инструментов, как фреймворки. Никто не был готов даже к переходу на высокоуровневые языки программирования, а о таких готовых решениях они не могли даже мечтать.
Мы находимся сейчас в такой же ситуации, лет через 10 программисты будут изучать сегодняшние перспективные фреймворки в ВУЗах как вводный исторический материал для подготовки к современным технологиям.
Необходимо понимать, что новые решения появляются лишь в момент, когда появляются конкретные задачи. Как говорится, спрос порождает предложение. Наверняка, пока вы дочитываете данную статью, какой-то программист создает новый прорывной проект, который изменит мир программирования, но мы узнаем об этом только через некоторое время. Для этого необходимо следить за миром новостей в программировании и постоянно изучать новые технологии."