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