Перейти к основному содержимому

5.16. О старых языках

Разработчику Архитектору Инженеру

Термин «старые языки» в данном контексте не несёт дисфункциональной или уничижительной окраски. Он обозначает языки, появившиеся в первые три десятилетия развития программирования (1950–1980-е годы), созданные в условиях жёстких аппаратных ограничений, отсутствия устоявшихся методологий разработки и незрелости самой дисциплины «программная инженерия». Эти языки — не просто исторические артефакты; они сформировали фундаментальную основу современного программного мира. Без понимания их генезиса невозможно в полной мере осознать эволюцию парадигм, конструкций и даже самой терминологии, которой пользуются сегодня.

Почему эти языки называют «старыми»?

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

  • Отсутствие значимой эволюции стандарта в последние 15–20 лет (не путать с сопровождением: COBOL и FORTRAN, например, продолжают обновляться, но эти изменения не меняют фундаментальной модели языка);
  • Сужение сферы применения до узких ниш, где его использование обусловлено историческими, экономическими или техническими причинами (например, необходимость поддержки legacy-систем);
  • Миграция сообщества разработчиков и образовательных программ к более поздним языкам, обладающим лучшей выразительностью, безопасностью, переносимостью или поддержкой современных парадигм;
  • Техническое несоответствие современным требованиям к продуктивности разработки (например, отсутствие встроенной поддержки многопоточности, сборки мусора, строгой типизации, модульности).

Существенно, что «старые» языки почти никогда не исчезают полностью. Они переходят в статус структурообразующих — их идеи, синтаксические паттерны и модели программирования становятся ДНК более поздних языков, а сами исходные системы продолжают функционировать в критически важных инфраструктурах.

Эволюционные связи и преемственность

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

  • FORTRAN → Algol → Pascal → Ada, Modula → (косвенно) C → C++/C#/Java/Go/Rust
    FORTRAN задал стандарт компилируемого языка высокого уровня для численных расчётов. Его прямой «оппонент» — Algol — ввёл строгую структуризацию кода, блочную структуру и формальный синтаксис, описанный в нотации Бэкуса–Наура (BNF). Algol, в свою очередь, стал прародителем Pascal (как учебного и системного языка) и повлиял на ранний C — последний, однако, отказался от некоторых строгостей Algol ради близости к железу, создав гибридную модель «высокоуровневого ассемблера». Именно C обеспечил массовый переход от научного программирования к системному и прикладному, а его синтаксис (фигурные скобки, for, while, if) стал де-факто стандартом для подавляющего большинства императивных языков последующих десятилетий.

  • COBOL → (влияние на) RPG, PL/I, Ada, бизнес-ориентированные DSL
    COBOL был разработан как язык, максимально приближенный к естественному (английскому), с целью сделать программирование доступным для аналитиков и экономистов. Его иерархическая структура данных (level numbers), вербальный синтаксис (MOVE A TO B, PERFORM UNTIL) и ориентация на обработку файлов и транзакций оказали влияние на специализированные языки делового программирования (например, IBM RPG) и на концепцию доменных языков (DSL). Хотя COBOL не имеет прямых «потомков» в виде общих языков, его философия — язык как спецификация бизнес-логики — живёт в современных low-code платформах, BPM-системах и языках вроде SQL (который, кстати, тоже концептуально близок к COBOL по декларативности и вербальности).

  • Lisp → Scheme, Common Lisp → Emacs Lisp, AutoLisp → Clojure, Racket, Julia (частично)
    Lisp — единственный из языков 1950-х, сохранивший не только актуальность, но и активное развитие. Его революционность состояла не в синтаксисе (скобки — лишь внешнее проявление), а в единообразии представления данных и кода. Программа на Lisp — это структура данных (список), и интерпретатор может её модифицировать во время выполнения. Эта идея гомоиконичности легла в основу метапрограммирования, макросистем и динамических языков. Lisp напрямую породил две ветви: Scheme (упрощённая, академическая, с упором на функциональность и рекурсию) и Common Lisp (практическая, стандартизированная). Современные языки вроде Clojure (работающий на JVM и CLR) и Julia (математические вычисления) напрямую заимствуют идеи Lisp: символы как данные, мощные макросы, REPL-ориентированная разработка.

  • Ассемблер (машинно-зависимый) → макроассемблеры → (влияние на) C, C++, Rust
    Ассемблер не является единым языком; это семейство языков низкого уровня, тесно связанных с конкретной архитектурой процессора (x86, ARM, MIPS и т.п.). Именно ассемблер определил базовые концепции: регистры, флаги, стек, прямую адресацию памяти, инструкции управления потоком. Хотя современные разработчики редко пишут на «голом» ассемблере, его логика пронизывает системное программирование. Язык C был задуман как переносимый ассемблер: каждая его конструкция (например, указательная арифметика, union, volatile) имеет прямое отображение в машинные инструкции. Rust, несмотря на высокий уровень безопасности, также сохраняет близость к железу — его модель владения (ownership) и unsafe-блоки — прямое наследие ассемблерно-ориентированного мышления.

  • BASIC → Visual Basic → VB.NET
    BASIC создавался как язык для начинающих, с упрощённым синтаксисом и интерактивной средой (REPL в виде командной строки). Его массовое распространение в 1980-х на домашних компьютерах (Commodore 64, ZX Spectrum, Apple II) сделало его первым языком для целого поколения программистов. Microsoft BASIC (а затем QBasic, QuickBASIC) добавил структурные элементы (SUB, FUNCTION), а Visual Basic (1991) совершил революцию: впервые связал язык с визуальным конструктором интерфейсов (RAD — Rapid Application Development). VB стал де-факто стандартом для Windows-приложений в 1990-х. VB.NET (2002), несмотря на названии, — это уже не BASIC, а полностью объектно-ориентированный язык, компилируемый в IL и работающий на .NET CLR, синтаксически совместимый с предшественником лишь на уровне поверхностных конструкций.

Кто кого заменил — и почему это не всегда полная замена

Важно избегать линейного нарратива «язык A устарел, его вытеснил язык B». На практике замена происходит по сегментам применения, и часто старый язык сохраняется там, где его замена экономически или технически невыгодна.

  • FORTRAN не был заменён C или C++ в научных вычислениях — он дополнился ими. Современные HPC-стеки часто используют гибрид: FORTRAN для ядер вычислений (из-за отлаженных библиотек, например, LAPACK, BLAS), а C/C++/Python — для интерфейсов, управления памятью и оркестрации. Причина — не «лучше/хуже», а непрерывность инвестиций: переписать 50 лет наработок в гидродинамике или квантовой химии — задача с колоссальным риском и стоимостью.

  • COBOL не заменён Java или C# в банковских системах — он интегрирован с ними. Современные решения используют «обёртки» (wrappers), ESB-шлюзы, API-фасады, чтобы COBOL-транзакции вызывались из Java-сервисов. Причина — надёжность, предсказуемость и соответствие регуляторным требованиям: в финансах важна не новизна, а отсутствие неопределённости.

  • Ассемблер не заменён C — он делегирован. Ядро ОС, драйверы, криптографические примитивы по-прежнему содержат вставки ассемблера (inline assembly) для достижения максимальной производительности или доступа к специфическим инструкциям (например, RDTSC, CPUID). Встраивание ассемблера в C — стандартная практика в системном программировании.

Таким образом, «замена» — это скорее перераспределение ролей: старый язык уходит из frontline-разработки, но остаётся в ядре инфраструктуры как «невидимая опора».

Где сейчас можно встретить старые языки

  • Финансовый сектор: более 43% транзакций в системах крупнейших банков США обрабатываются на COBOL (оценка Reuters, 2020). Триллионы строк кода, запущенные на мейнфреймах IBM z/OS.
  • Научные исследования: FORTRAN — основной язык в физике, метеорологии, аэрокосмической отрасли. Код, разработанный в 1970-х, всё ещё используется в NASA и Европейском центре среднесрочных прогнозов погоды (ECMWF).
  • Встроенные и реального времени системы: Ассемблер и C доминируют в микроконтроллерах, автомобильной электронике (AUTOSAR), авионике (DO-178C сертификация). Pascal (в виде Object Pascal/Delphi) встречается в медицинском оборудовании и промышленных ПЛК.
  • Наследственные ПО для Windows: тысячи корпоративных приложений на Visual Basic 6.0 всё ещё поддерживаются. Microsoft прекратила официальную поддержку в 2008, но runtime распространяется и сегодня.
  • Образование и ретрокомпьютинг: BASIC (в современных интерпретаторах, например, QB64), Pascal (Free Pascal, Lazarus) используются в школах и университетах для обучения основам алгоритмики. Энтузиасты воссоздают игры для Commodore 64 и ZX Spectrum на оригинальных языках.
  • Метапрограммирование и ИИ: Lisp и его диалекты применяются в символьных системах ИИ, expert systems, в редакторе Emacs (весь UI — на Emacs Lisp), в AutoCAD (AutoLisp), в некоторых DSL для финансового моделирования.

COBOL (Common Business-Oriented Language)

COBOL был разработан в 1959–1960 гг. по инициативе комитета CODASYL при участии Грейс Хоппер. Его появление стало ответом на растущую потребность в автоматизации бухгалтерского и банковского учёта — задач, где доминировала обработка больших объёмов структурированных данных (карты, ленты), а не численные расчёты.

Ключевая особенность COBOL — вербальная избыточность. Синтаксис строится по принципу «читаемость превыше краткости»: ADD A TO B GIVING C, IF CUSTOMER-STATUS = 'ACTIVE' THEN PERFORM CALCULATE-DISCOUNT. Это было осознанное проектировочное решение: язык должен был быть понятен не программистам, а бизнес-аналитикам, которые писали спецификации. Отсюда и четырёхчастная структура программы (Identification, Environment, Data, Procedure Division) — она отражает жизненный цикл обработки: кто, где, с чем, как.

COBOL первым ввёл строгую иерархическую модель данных с level numbers (например, 01 CUSTOMER. 05 NAME PIC X(30). 05 ACCOUNTS OCCURS 10 TIMES.), предвосхитив концепцию вложенных структур и массивов записей. Его модель файлового ввода/вывода (sequential, relative, indexed) легла в основу транзакционных систем: каждая транзакция — это последовательность операций над записями, с чётким разделением на открытие, обработку, закрытие.

COBOL не «умер» — он консервировался. Сегодня около 220 млрд строк COBOL-кода поддерживаются в мире (оценка Reuters, 2023), преимущественно в банковских ядрах (core banking systems), пенсионных фондах и страховых компаниях. Причины устойчивости:

  • Надёжность: программы, отлаженные десятилетиями, обрабатывают миллионы транзакций без сбоев;
  • Соответствие регуляторным нормам: проверки COBOL-систем прошли аудиты десятки лет подряд;
  • Стоимость миграции: перепись одного среднего банка может стоить от $50 млн и занять 5+ лет при высоком риске ошибок.

COBOL оказал прямое влияние на развитие декларативных и специализированных языков: его идея «описать задачу, а не алгоритм её решения» предвосхитила SQL, а структура Data Division — форматы вроде XML Schema и Protocol Buffers.


FORTRAN (FORmula TRANslation)

FORTRAN, созданный в 1954–1957 гг. в IBM под руководством Джона Бэкуса, — первый в мире практически успешный язык высокого уровня. До него программирование велось исключительно на машинных кодах или ассемблере, и переход на FORTRAN означал ускорение разработки в 10–20 раз — революционный эффект для своего времени.

FORTRAN проектировался для одной цели: максимально эффективная компиляция математических формул. Отсюда — его синтаксис, близкий к научной нотации (X = A * SIN(B) + C**2), поддержка комплексных чисел и массивов, а также ранние оптимизации компилятора (loop unrolling, common subexpression elimination), которые были невозможны в интерпретируемых языках. FORTRAN-77 стандартизировал функциональный подход: подпрограммы (FUNCTION, SUBROUTINE) стали основной единицей модульности.

Критически важно: FORTRAN задал парадигму вычислительного кластера. Уже в 1960-х годах FORTRAN-программы распределялись по нескольким процессорам (на CDC 6600), заложив основы MPI-подобных моделей. Библиотеки вроде LINPACK (1970-е) и LAPACK (1990-е) — написаны на FORTRAN — до сих пор используются как эталон производительности в суперкомпьютерных рейтингах TOP500.

Сегодня FORTRAN применяется там, где доминируют:

  • Долговечность вычислительных моделей (например, климатические модели, разработанные в 1980-х, до сих пор в эксплуатации);
  • Производительность для dense linear algebra (матричные операции);
  • Соответствие стандартам в инженерных расчётах (ANSI/IEEE 754 для арифметики).

Наследие FORTRAN — не в синтаксисе, а в культуре научных вычислений: идея «написать ядро на низкоуровневом, но эффективном языке, а обвязку — на другом» — прямая проекция FORTRAN/C/Python-стека современных HPC-приложений.


Ассемблер (Assembly Language)

Ассемблер — не единый язык, а класс языков, каждый из которых представляет собой мнемоническое отображение инструкций конкретного процессора. Первые ассемблеры появились в 1949–1951 гг. (например, для EDSAC), заменив ручное кодирование в двоичных перфокартах. Их цель — автоматизировать адресацию и расчёт смещений, сохранив при этом полный контроль над железом.

Особенность ассемблера — полная прозрачность: каждая инструкция (MOV, ADD, JMP) соответствует одной машинной команде. Это даёт максимальную производительность и предсказуемость по времени выполнения — критично для реального времени. Однако цена — отсутствие переносимости и высокая сложность поддержки: изменение архитектуры (например, переход с x86 на ARM) требует полного переписывания.

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

  • Регистровая модель (general-purpose, status, stack pointer);
  • Стек как структура управления вызовами;
  • Прямая адресация памяти (absolute, relative, indexed);
  • Прерывания и обработка исключений.

Современное применение:

  • Ядра операционных систем: критические секции (context switching, TLB flush) часто написаны на ассемблере;
  • Криптография: реализации AES, SHA-256 используют специализированные инструкции (AES-NI, AVX);
  • Встроенные системы: микроконтроллеры с объёмом памяти < 64 КБ (например, в бытовой технике);
  • Отладка и реверс-инжиниринг: дизассемблирование остаётся основным методом анализа бинарного кода.

Ассемблер не эволюционировал — он специализировался. Современные макроассемблеры (NASM, MASM) добавили условную компиляцию и макросы, но ядро осталось неизменным: язык остаётся инструментом для тех, кто должен говорить с процессором напрямую.


Lisp (LISt Processor)

Lisp, созданный Джоном Маккарти в 1958 г., — первый функциональный язык и, по сути, первый язык с поддержкой метапрограммирования на уровне языка. Его революционность — в единстве кода и данных: программа на Lisp записывается как s-выражение (вложенный список), и интерпретатор может обрабатывать этот список как данные, модифицировать его и затем выполнять. Отсюда — eval, quote, macroexpand как встроенные примитивы.

Lisp ввёл:

  • Условные выражения (cond);
  • Рекурсию как основной инструмент итерации (циклы появились позже);
  • Автоматическое управление памятью (первый в мире сборщик мусора, 1960);
  • Динамическую типизацию и REPL (Read-Eval-Print Loop) как основной режим работы.

Lisp не был массовым, но стал языком исследований: на нём создавались первые экспертные системы (DENDRAL, MYCIN), символьные системы ИИ, системы автоматического доказательства теорем. Его гибкость делала его идеальным для прототипирования новых идей — многие концепции (замыкания, continuation, pattern matching) впервые были реализованы в диалектах Lisp.

Современное положение:

  • Emacs Lisp — весь пользовательский интерфейс редактора Emacs (окна, меню, плагины) написан на нём;
  • AutoLisp — встроенный язык в AutoCAD для автоматизации черчения;
  • Common Lisp и Scheme — используются в академической среде, а также в нишевых коммерческих продуктах (например, ITA Software, купленная Google, использовала Common Lisp для маршрутизации авиабилетов);
  • Clojure — современный Lisp, работающий на JVM и CLR, активно применяется в финтехе (Nubank, Walmart) и аналитике.

Lisp доказал: язык может быть расширяемым до неузнаваемости, оставаясь при этом строго формальным. Эта идея легла в основу макросистем в Rust, Julia, Scala и даже в препроцессорах C++ (хотя и в ограниченной форме).


Pascal

Pascal был разработан Никлаусом Виртом в 1968–1970 гг. как учебный язык, призванный продемонстрировать преимущества структурного программирования — подхода, противопоставленного «спагетти-коду» на ранних версиях FORTRAN и BASIC. Pascal строго реализовывал идеи Эдсгера Дейкстры: запрет goto, блочная структура, строгая типизация, явное объявление всех переменных.

Ключевые нововведения:

  • Записи (record) — первая реализация структур с именованными полями разного типа;
  • Множества (set of) — аппаратная поддержка битовых масок;
  • Процедуры и функции как первоклассные сущности (но без замыканий в оригинальной версии);
  • Модульность через внешние файлы (позже — unit в Turbo Pascal).

Pascal достиг пика популярности в 1980-х благодаря Turbo Pascal от Borland (1983) — первой IDE с компилятором, редактором и отладчиком в одном пакете, загружавшемся за секунды на PC с 64 КБ ОЗУ. Turbo Pascal и его потомок — Delphi (1995, Object Pascal) — определили поколение Windows-разработчиков. Delphi с его VCL (Visual Component Library) был одним из первых RAD-инструментов, предвосхитив C# WinForms и Java Swing.

Сегодня Pascal живёт в:

  • Free Pascal / Lazarus — кроссплатформенная среда для встраиваемых и десктопных приложений;
  • Эмбаркадеро Delphi — поддержка legacy-приложений в банковской и медицинской сферах (особенно в странах Восточной Европы и Латинской Америки);
  • Обучении — в ряде вузов (например, в Германии, России) Pascal по-прежнему используется для вводного курса по алгоритмам.

Pascal оказал влияние на Ada (который частично базировался на его типовой системе) и на ранний Си++ (Бьёрн Страуструп признавал влияние Pascal на концепцию class как расширенной record).


BASIC и Visual Basic

BASIC (Beginner’s All-purpose Symbolic Instruction Code) был создан в 1964 г. в Дартмутском колледже как язык для студентов, не специализирующихся в информатике. Его принцип — минимизация барьеров входа: интерактивный режим, автоматическая нумерация строк, отсутствие компиляции, простейший синтаксис (PRINT "HELLO", GOTO 100).

Массовое распространение BASIC получил благодаря домашним компьютерам 1980-х: Commodore 64, ZX Spectrum, Apple II поставлялись с интерпретатором BASIC в ПЗУ. Это сделало его первым языком для миллионов. Однако его изначальная простота обернулась проблемами: отсутствие процедур, глобальные переменные по умолчанию и GOTO вели к нечитаемому коду — отсюда и фраза «BASIC портит стиль».

Перелом наступил с QuickBASIC (1985) и QBasic (1991), добавившими процедуры, типизацию и отладчик. Но настоящая революция — Visual Basic 1.0 (1991). VB объединил:

  • Простоту BASIC;
  • Визуальный конструктор форм (drag-and-drop);
  • Модель событий (Button_Click);
  • COM-интеграцию (позволявшую вызывать DLL и ActiveX-компоненты).

VB стал стандартом для внутренних корпоративных приложений в 1990-х. По оценкам Microsoft, в 1998 г. на VB приходилось 70% всех Windows-приложений.

VB.NET (2002) — уже не BASIC. Это объектно-ориентированный язык, компилируемый в CIL, с перегрузкой, исключениями, обобщениями. Совместимость с VB6 — лишь частичная (синтаксическая), семантически это другой язык. Тем не менее, миллионы строк VB6 до сих пор поддерживаются через режим совместимости или посредством инструментов вроде ArtinSoft Visual Basic Upgrade Companion.

Наследие BASIC — идея доступности программирования. Современные low-code платформы (Power Apps, OutSystems), языки вроде Scratch и даже Python (в части своей философии «читаемости») — прямые наследники BASIC-подхода.


Си (C)

Си, разработанный Деннисом Ритчи в Bell Labs в 1969–1973 гг., — не просто язык, а мост между аппаратным и программным мирами. Он возник как инструмент переписывания ядра Unix с ассемблера PDP-7 на более переносимый язык. Результат превзошёл ожидания: Unix, написанный на C, был портирован на PDP-11 — и с тех пор C стал языком системного программирования по умолчанию.

C — компромисс между выразительностью и контролем. Он предоставляет:

  • Указатели и арифметику над ними — прямой доступ к памяти;
  • Структуры (struct) и объединения (union) — гибкое представление данных;
  • Преобразование типов (cast) — явное управление интерпретацией битов;
  • Минимальную runtime-поддержку — программа может состоять из одной функции main.

Критически: C не определяет поведение при ошибках (например, выход за границы массива, разыменование нулевого указателя). Это не «недостаток», а проектировочное решение: контроль передаётся разработчику, а компилятор не вносит «невидимых» проверок, снижающих производительность.

Влияние C невозможно переоценить:

  • Операционные системы: Unix, Linux, Windows NT (ядро), macOS, Android (ядро Linux);
  • Компиляторы и интерпретаторы: GCC, Clang, CPython, V8 (часть runtime);
  • Базы данных: MySQL, PostgreSQL, SQLite;
  • Сетевые протоколы: реализации TCP/IP, OpenSSL.

Синтаксис C (фигурные скобки, if/else, for, while, ; как разделитель) стал основой для C++, Java, C#, JavaScript, PHP, Go, Rust — даже в языках с иной семантикой (например, в функциональных) часто сохраняется C-подобная нотация для управляющих конструкций.

C не «устарел» — он стабилизировался. Стандарт C17 (2018) ввёл лишь незначительные уточнения; C23 (2023) добавил UTF-8 поддержку, но не изменил модель памяти. Причина — в надёжности базы: если язык позволяет написать ядро ОС, то его «улучшение» — это риск, а не выгода.