Найти тему
IT. Как это работает?

Архитектурная космонавтика на языке Си

Оглавление

Общепринято считать, что каждый язык программирования имеет свою нишу. Такое миропонимание появившись некогда на горизонте, вырастало в размерах пока окончательно не затмило разум большинству. Благодаря новым языкам и технологиям, порог вхождения в программирование настолько снижен, что человек, увлеченно читающий одну книжку может настойчиво заявлять: "Python это язык анализа данных". В целом, это и неплохо. Значит труд других программистов не прошел даром. Сейчас постараемся разобраться как проектируются сложнейшие программные системы вроде компиляторов языков, виртуальных машин и хранилищ данных, которые нужно анализировать.

В начале было Слово...

Ассемблер

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

FORTRAN

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

Текст программы на языке FORTRAN
Текст программы на языке FORTRAN

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

Язык Си

Эта история уже сродни рассказам о библейских событиях. В недрах телефонной компании Bell трудились два программиста, автоматизирующие процессы, происходящие на телефонных станциях. Быть может это была обработка ввода пользовательских команд ("наберите на телефоне *999 и поучаствуйте в скидочной лотерее"). Все общие самые часто используемые программами функции собирались в некоторый пласт исходного кода, из которого формировался образ будущей операционной системы.

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

В итоге: программист имеет дело с довольно высокоуровневыми абстракциями, но на процессоре исполняется быстрый машинный код.

Начало всего сущего

Весьма философский подзаголовок, однако язык Си в 80-е годы являлся тем самым "большим взрывом", породившим нашу IT вселенную. Страшно представить сколько программных продуктов и технологий написано на этом языке.

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

Объектно-ориентированная парадигма

Идея выделения цельных сущностей в объекты (классы), имеющие характеристики (поля) и методы работы с ними это не более чем идея. Однако, она многим показалась удобной и даже способствовала рождению новых языков программирования. Вместе с этим, идея никак не повлияла на развитие полупроводниковой промышленности и память с процессором остались все теми же кусками кремния. Языки это всего-лишь способ описать наши мысли.

Диаграмма классов с взаимоотношениями между ними
Диаграмма классов с взаимоотношениями между ними

Язык Си, являясь близком к "железу", способен описать класс, как структуру данных с полями и методами. Благо, что синтаксически мы можем описать указатель на функцию (метод), а процессор в состоянии передать управление по программному коду, расположенному по этому адресу. Более подробно об этом можно почитать в статье про сущность объектно-ориентированного программирования.

Расставляем объекты по полочкам

То что сейчас будет наброском кода весьма популярной в прошлом игры раньше делалось при помощи ассемблера и совсем не предполагало объектно-ориентированности. Однако, в крупных проектах необходимо цельное видение архитектуры кода и системный подход. На малом показываем большое.

Скриншот из игры PacMan
Скриншот из игры PacMan

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

Поле игры представляет собой массив M*N элементов, каждый из которых может хранить: ничего, таблетку, супер таблетку, главного героя, призрака, кусок непроходимой стены.

Элементы игрового поля
Элементы игрового поля

"Объектно-ориентированный" программист сразу смекает: двумерный массив содержит единообразные объекты-ячейки (Tile), которые содержат другие (разнообразные) объекты:

Каждая ячейка обладает логическим признаком обладания чего-либо (стены, героя, призрака, таблетки, мощной таблетки). Свойствами ячейки является ее координаты на плоскости.

В каждой ячейке может быть какой-то из двух персонажей, но чтобы единообразно содержать эти разные объекты в одном массиве, требуется создание общего предка (Character), берущего на себя, кроме всего, базовые методы персонажей. Персонажи могут унаследовать базовые методы, а могут их переопределить по-своему.

Определенно, каждый персонаж обладает координатами на плоскости, скоростью и направлением передвижения. Базовыми методами являются проверка на столкновение со стеной и движение.

Персонажи в данном случае переопределяют способ движения (с разной скоростью и направлением), а главный герой еще и имеет дополнительные свойства (сколько таблеток съедено, время до окончания "мощного режима" и включен ли "режим мощности").

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

Для общей картины архитектуры программы не хватает рассмотрения различных возможных взаимосвязей между объектами, но это уже выходит за лимит количества печатных символов за сегодня, поэтому о Композиции, Агрегации, Интерфейсе и Зависимости в другой раз.

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

Поддержите статью лайком если понравилось и подпишитесь чтобы ничего не пропускать.

Также не обойдите вниманием канал на YouTube. Подписки и лайки будут приятным ответом от аудитории.