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

Компилятор. Транспайлер. Устный переводчик. Время выполнения. JIT. АОТ. Это лишь некоторые из слов, которые разработчики произносят так же небрежно, как дни недели. Как новичок, одна из самых пугающих вещей в разработке - самая фундаментальная: как вообще работает наш код?

Что ж, если вы читали мою статью Rest API </subtle-plug>, то знаете, что мне нравится начинать с основ.

Машинный код

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

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

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

Излишне говорить, что до этого был долгий путь.

сборка

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

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

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

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

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

Компиляторы

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

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

Переводчики

Разница между компилятором и интерпретатором в некотором роде похожа на разницу в реальной жизни между переводчиком и… ну, интерпретатором.

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

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

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

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

Разные термины и нюансы

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

Таким образом, скомпилированные языки обычно считаются языками более низкого уровня, а интерпретируемые языки - более высокими уровнями.

JIT против AOT. По мере того, как они набирали популярность, все больше и больше программного обеспечения было написано на интерпретируемых языках. Часть этого кода предназначалась для интенсивного выполнения, что требовало повышения производительности. Для этого некоторые интерпретаторы также начали действовать как частичные компиляторы. Они пытаются определить, какие части кода используются наиболее часто, и временно компилируют эти части в собственный код, чтобы он работал быстрее. Этот процесс называется компиляцией во время выполнения или JIT-компиляцией (Just-In-Time). Этому термину противопоставляется термин AOT (Ahead-Of-Time), который относится к традиционно компилированному коду.

Транспилятор. В отличие от компилятора, который переводит код более высокого уровня в код более низкого уровня, транспилятор переводит один язык высокого уровня на другой язык высокого уровня. Транспилеры наиболее распространены в веб-разработке, где они используются для преобразования расширенных версий JavaScript (таких как TypeScript или JSX) в «ванильный» JavaScript, который могут выполнять браузеры.

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

В: Как вы можете отличить компьютерного ученого от компьютерного инженера?

A: Ученый начнет предложение со слов «На языках низкого уровня, таких как C ++…», а инженер начнет со слов «На языках высокого уровня, таких как C ++…»

Мейт Сафранка - фронтенд-разработчик в Supercharge. Если вам понравилось то, что вы здесь читали, возможно, вас заинтересуют другие его статьи о Rest APIs или HTTP и WebSockets.