Рассказываю о том, почему языки программирования делятся на уровни, что эти уровни обозначают и с какого уровня стоит начинать обучение.
Язык программирования – это набор инструкций, с помощью которых можно передавать команды процессору и тем самым управлять компьютером. Существует множество языков со своим специфичным синтаксисом и все они позволяют вносить изменения в данные, хранящиеся на компьютере, менять контент, отображающийся на экране, запускать приложения, производить вычисления и т.п.
Разные языки программирования на разных уровнях взаимодействуют с компьютером, потому что машина не понимает английский (или любой другой человеческий язык), и для взаимодействия с ним используется специальная система из нулей и единиц. Но развитие технологий привело к созданию новых языков и деление их на уровни.
Низкоуровневые языки
Как я уже отметил выше, компьютер не умеет разговаривать по-английски. Общение с машиной происходит при помощи нулей и единиц. Мы буквально подаем ток на определенные транзисторы, чтобы превращать импульсы тока в слова, изображения на экране компьютера, сложные программы и видеоигры. Это наиболее рациональный с точки зрения производительности вариант взаимодействия с процессором, потому, используя двоичную систему, вы передаете команды напрямую: управляете памятью, перемещаете данные и т.п.
Но есть низкоуровневые языки, которые немного упрощают процесс общения с «железом» за счет преобразования часто используемых команды из 1011 в более удобоваримые директивы в духе MOV, AAD.
Такие языки строго оптимизируются под конкретные чипы и работают только на тех архитектурах, под которые они изначально разрабатывались.
Машинный язык
Это единственный язык, который понимает компьютер без какой-либо предобработки. Сейчас программисты его не используют, потому что он слишком сложный в восприятии. Есть масса более понятных аналогов, выполняющих те же функции, в то время как машинный язык очень сложный, требует куда больше времени и внимательности от специалиста и вообще никак не помогает в создании новых программ, а только усложняет эту задачу.
Машинный язык – это информация в чистом виде, зачастую представляющая собой набор чисел в двоичной системе исчисления (иногда используются десятичные и другие варианты). Разработчики должны прописывать каждую команду с помощью заранее предусмотренных запросов, четко следуя правилам написания инструкций для конкретного чипа, с которым работает программист.
Написанный машинный код передается в загрузчик программ напрямую, обычно игнорируя любые посреднические программные слои.
Языки ассемблера
Это первый уровень абстракции от машинного языка. Первая надстройка, упрощающая восприятие программного кода и помогающая разработчикам писать более стабильные приложения, практически не теряя в производительности.
Синтаксис языка ассемблера состоит не из нулей и единиц (и даже не из цифр с буквенными значениями, как в десятичной системе), а из вполне читаемых директив, которые похожи на сокращенные английские слова. Например MOV вместо 1011 отвечает за перемещение данных из одного регистра в другой.
Каждый язык ассемблера поставляется с собственным переводчиком, превращающим директивы на английском языке в директивы, которые умеет читать компьютер, то есть в машинный код. Этот переводчик называют ассемблером. И это одна из причин, почему ПО, написанное с использованием ассемблера работает медленнее, – компьютеру требуется время на перевод.
Уровень абстракции языка ассемблера довольно посредственный, потому что информация, которой манипулирует разработчик, хранится в регистрах процессора (специальных ячейках, где может храниться определенный объем данных), из-за чего формируется тесная взаимосвязь между написанным кодом и используемым железом. Без больших затрат по времени ретранслировать этот код под другую платформу или операционную систему не получится.
В отличие от машинного языка, язык ассемблера используется даже в современной разработке. В частности, для создания ПО, требующего очень высокой производительности, низкоуровневых системных компонентов или драйверов для аппаратной части устройств.
Краткое сравнение ассемблера и машинного языка
Резюмируем:
Машинный код |
Язык ассемблера |
Нулевой уровень абстракции. Полный контакт с аппаратной составляющей компьютера |
Первый уровень абстракции. Есть прослойка в виде переводчика-ассемблера |
Трудно понять, что написано в коде |
Код больше похож на человеческий язык |
Для запуска не нужны дополнительные инструменты |
Требуется ассемблер для превращения кода в машинный язык |
Синтаксис состоит из нулей и единиц |
Синтаксис состоит из английских слов |
Высокоуровневые языки
Машинный код сложен для восприятия, и это порождает две большие проблемы в разработке:
-
Чтобы научиться программировать, нужно потратить много времени на изучение разных директив и понять, как они взаимодействуют друг с другом и с физическими компонентами компьютера.
-
Синтаксис машинного кода настолько мудреный, что писать программы, не допуская ошибок, почти нереально. Нужно быть крайне внимательным.
В связи с этим инженеры начали создавать дополнительные уровни абстракций для машинного языка, чтобы люди могли выполнять те же операции, но манипулируя куда более понятными для них структурами, отсекая часть задач, ранее возложенных на программиста, и передавая их специализированным компьютерным утилитам.
Высокоуровневые языки куда ближе к английскому языку, чем язык ассемблера и машинный код. Поэтому его проще воспринимать, и новые поколения программистов начали расти куда быстрее за счет использования более простых конструкций в коде.
Особенности высокоуровневых языков
Код, написанный на высокоуровневом языке, впоследствии трансформируется в машинный код при помощи специальных утилит: компиляторов и интерпретаторов. Первый трансформирует программу в понятную для компьютера еще до запуска, а второй делает это постепенно – строка за строкой.
Такой подход позволил создать множество уникальных синтаксисов и надстроек. Каждый вариант позволяет выполнять свои задачи по-разному, взаимодействуя с железом.
Взаимодействуя с высокоуровневыми языками, программист переходит на управление абстрактными структурами. На смену регистрам, адресам памяти и запросам в стек (это список команд, если выражаться максимально примитивно) приходят объекты, массивы данных, переменные, булевы выражения, функции, циклы и другие сущности, знакомые современным разработчикам.
Частицы кода больше напоминают прикладные и «осязаемые» элементы, в которые проще уложить логику сложных современных приложений и веб-сайтов.
Плюсы высокоуровневых языков
-
Главный плюс – абстракция. Современные разработчики не обязаны знать, как устроен компьютер и как с ним общаться с помощью нулей и единиц. Они могут создавать продвинутые приложения без глубоких познаний в области информатики.
-
Помимо низкого порога вхождения, высокоуровневые языки обеспечивают более богатый арсенал инструментов. В их числе специальные модули для автоматического выявления ошибок в коде и объединения нескольких видов технологий в одну рабочую среду (несколько фреймворков, сборщики по типу Webpack и т.п.).
-
ПО стало портативным. Одну базу кода можно использовать сразу на нескольких платформах. Мощные интерпретаторы в полуавтоматическом режиме превращают код на одном языке в код для нескольких отличающихся друг от друга ОС.
Минусы высокоуровневых языков
-
Низкая производительность. Чем выше уровень абстракции, тем больше времени и ресурсов компьютера тратится на «перевод» одного языка в другой. Поэтому некоторые приложения, даже будучи не слишком функциональными, долго загружаются или работают нестабильно.
-
Не особо смышленые программисты. Многие разработчики не углубляются в теоретическую базу и остаются на уровне своего языка, что сильно ограничивает их кругозор и не позволяет расти с профессиональной точки зрения. Притупляется внимание, страдают навыки поиска и инженерное мышление.
-
Избыточное внимание к инструментам. Количество дополнительных слоев абстракции становится избыточным. Регулярно появляются новые фреймворки, редакторы кода, дополнительные вспомогательные приложения, языки, стандарты и т.п. Фокус часто смещается с создания хороших программ на перебор утилит и споры о том, какие из них работают лучше.
Популярные высокоуровневые языки программирования
Их уже довольно много:
-
C – язык общего назначения, лежащий в основе десятков других языков.
-
C++ – расширенная версия C. До сих пор в почете и используется в разработке сложных приложений, например музыкальных плагинов и редакторов кода.
-
Java – мультипрофильный язык, который позволяет запускать единожды написанный код на десятках устройств и систем.
-
Python – простой в освоении язык общего назначения с «аккуратным» синтаксисом и большим количеством расширений.
-
JavaScript – скриптовый язык, выросший из эксклюзивной веб-технологии в мощный язык для создания приложений, игр, IDE даже других языков.
Естественно, языков в десятки раз больше, но на всех в этой статье места не хватит. Если интересно, почитайте статью на Википедии со списком всех известных языков программирования.
Степень высокоуровневости
Относительность термина «высокоуровневый» возникла в связи с избыточным ростом количества языков программирования. Причем многие из них базировались друг на друге и семимильными шагами повышали уровень абстракции.
Некоторые языки считаются более низкоуровневыми, чем другие, даже в пространстве высокоуровневых. Например, C++ более тесно взаимодействует с «железом», а потому нередко именуется низкоуровневым языком, хотя таковым и не является.
А все потому что появились языки в духе JavaScript, которые еще больше отдаляют программистов от аппаратных компонентов и создают тепличные условия, в которых разработка все меньше походит на хардкорную борьбу с машиной 30 лет назад.
Также низкоуровневыми начали называть языки, в которых по умолчанию не встроены дополнительные инструменты, облегчающие процесс создания ПО, например «сборщики мусора».
Краткое сравнение высокоуровневых и низкоуровневых языков
Резюмируем:
Низкоуровневые |
Высокоуровневые |
Наиболее понятный для компьютера язык с синтаксисом из нулей и единиц или простых команд для взаимодействия напрямую с «железом» компьютера |
Наиболее понятный для человека язык. Больше напоминает английский
|
Позволяет создавать более производительный код. |
Генерирует код, который требует больше ресурсов и времени для запуска |
Даже при использовании языка ассемблера перевод происходит единожды самим ассемблером |
Требует наличие компилятора или интерпретатора для преобразования человекоудобного кода в машинный код |
Создает код, который работает на конкретном устройстве |
Создает портативный код, который можно запускать на разных устройствах |
Эффективен с точки зрения использования памяти |
Менее эффективен с точки зрения использования памяти |
Поиск и устранение ошибок занимают много времени |
Есть инструменты для быстрого автоматического отлова ошибок |
Что учить и зачем?
Если вы только начинаете свой путь в мире разработки, то сразу бросаться в языки ассемблера и уж тем более машинный код не стоит. Программирование – тема сложная, и лучше начинать с определенного уровня абстракции. Хотя бы C++, но куда лучше подойдет Python. Последний поможет понять базовые концепции и выучить простейшие алгоритмы. А дальше у вас будет два пути:
-
Выбрать один из высокоуровневых языков в зависимости от того, какое программное обеспечение вы хотите создавать и для каких операционных систем.
-
Начать углубленное изучение низкоуровневых языков, чтобы в дальнейшем создавать драйверы и микропрограммы для чипов.
Вместо заключения
Низкоуровневые и высокоуровневые языки хоть и разные, но отлично уживаются в современном мире, выполняя задачи, возложенные конкретно на них. Благодаря повышению уровня абстракции был создан весь современный цифровой мир, поэтому корить разработчиков за то, что они используют только условный Objective-C и игнорируют машинный код, нелепо. Но и совсем отрицать важность изучения основ тоже глупо. Чтобы быть хорошим специалистом, нужно поддерживать баланс и изучать программирование со всех сторон.
Комментарии