Программирование в двух словах#

Основные определения#

Философия из всех наук самая «фундаментальная». Поэтому и мы начнем с понятийного аппарата — то есть, с точного значения слов.

  • Информация — структурированные данные о мире.
    Мир состоит из единичных фактов, информация — из единичных данных об этих фактах. Данные, описывающие объект, по отдельности называются его свойствами, а вместе — его состоянием.

  • Исполнитель — объект, способный выполнять действия.
    Выполнение действий может менять (а могут и не менять) свойства исполнителя, тем самым переводя его из одного состояния в другое. Все возможные состояния и переходы между ними образуют граф состояний.

    Если количество состояний исполнителя конечно, а переходы точно определены, то исполнитель называется конечным автоматом.

  • Алгоритм — последовательность действий, выполняемых исполнителем.
    Для решения задачи. В графе состояний это маршрут, двигаясь по которому, исполнитель достигает цели.

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

  • Команда
    это понятный исполнителю сигнал для выполнения действия. Полный набор таких команд называется языком исполнителя.

  • Программа
    запись алгоритма на языке исполнителя.

Информация#

Информатика – наука о методах хранения, передачи и обработки информацию.

Информация состоит из единичных фактов, которые можно представить числами, понятиями, категориями.

Представление. Нематериальная информация содержится в структуре материальных объектов. Зарубки на дереве, электрический потенциал в элементах микросхемы — все это содержит информацию.

Носитель. Носителем информации является материальный объект или среда, в структуре которого можно переносить информацию в пространстве или во времени. Электромагнитное поле способно переносить информацию в пространстве, архивный документ — во времени, а бумажное письмо — и в пространстве, и во времени.

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

Сообщение. Сообщение — передача информации при помощи сигналов от источника к получателю. Сигналы могут отправляться “в никуда”, а у сообщения всегда есть получатель. Письмо адресовано лично получателю, сводка новостей предназначена всем радиослушателям. Граница довольно условная: радио, которое никто не слушает — это сигнал, а популярное шоу с миллионной аудиторией — сообщение.

Кодирование. Кодированием называется преобразование информации из одного вида в другой. Звук можно перевести в электромагнитные колебания, идеи и мысли — в слова, изображение — в оттенки светового потока. Это кодирование.

Декодирование. Электромагнитные колебания при помощи громкоговорителя можно преобразовать обратно в звук, текст можно прочесть и понять, оттенки света воспроизвести на экране и увидеть изображение. Это декодирование. Если закодировать звук и попытаться из него декодировать изображение, то получим “цветомузыку” — явление интересное, но малополезное. Поэтому процессы кодирования и декодирования должны быть строго противоположным друг другу, чтобы информация восстанавливалась в первоначальном виде.

Потери. При записи звука какая-то его часть останется за пределами чувствительности микрофона. Какой-то диапазон частот не сможет воспроизвести мембрана акустической системы. Фотография не передаст всего, что сможет увидеть человеческий глаз. Даже текст — отражение идей и мыслей — при переводе на другой язык неизбежно потеряет оттенки смысла. В силу несовершенства мира и особенностей представления информации потери в той или иной мере будут всегда.

Шум. Треск в радиоэфире может заглушить музыку. Это шум — изменения в структуре носителя, не несущие информацию. Если соотношение сигнал/шум велико, то потери будут минимальными, если наоборот — максимальными, вплоть до полной потери информации.

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

Обработка. Можно сохранить записи сотен музыкальных композиций, а затем из пересчитать по исполнителям, жанрам, альбомам, популярности и так далее. В результате получится набор какой-то новой информации в виде индексов и рейтингов. А еще можно внести исправление в уже существующие данные: очистить звук, перевести в другой формат, удалить дубликаты. Все это — внесение изменений и создание новой информации — называется обработкой информации. Кодирование и декодирование тоже относятся к процессам обработки информации.

Электронно-вычислительной машины#

Вся история вычислительной техники это попытки заставить изобретение Эдисона приносить больше пользы, чем уличное освещение.

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

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

Компаратор — это схема из двух триодов, которая сравнивает произвольный ток на одном входе с эталонным на другом и на выход подает либо эталонный ток, либо его отсутствие. Это как точка и тире в азбуке Морзе — для передачи осмысленного сообщения двух сигналов достаточно1.

Только здесь это будут не точки и тире, а перепад напряжения в 5V.

Схема с двумя входами и одним выходом называется сумматором, если сигнал на выход появляется тогда, когда он есть хотя бы на одном входе.

Схема с двумя входами и одним выходом называется мультиплексором, если сигнал на выходе появляется только тогда, когда он подается на оба входа.

Схема, которая получает один сигнал, а выдает другой, называется инвертором.

Это электрическая схема, которая способна быть в двух состояниях и между ними переключаться. Между переключениями триггер помнит свое состояние. Ту “морзянку”, которую порождают логические схемы, триггеры запоминают.

Несколько триггеров, собранных вместе называются регистрами. Регистр предназначен, чтобы хранить больше информации, чем просто 0 и 1.

Устройство из регистров и логических схем и есть процессор. Все, что он умеет - это работать с сигналами в регистрах, складывать, инвертировать, умножать. Но это самая главная часть электронно-вычислительной машины, её “мозг”.

Без внешних устройств вычислительная машина подобна мозгу без “рук” и “глаз”. Внешние устройства нужны для того, чтобы внутрь поступали исходные данные для вычислений, а наружу - результат этих вычислений.

Системы счисления#

А, собственно, почему человек пользуется десятичной системой счисления? Потому, что изначально для счета использовались пальцы рук. Двурукие шестипалые существа пользовались бы двенадцатеричной системой счисления, трехрукие - восемнадцатиричной. Никакой разница, на самом деле. Кому как удобней. Нам, двуруким пятипалым, удобней десятичная.

Число 10 - это основание десятичной системы. Арабских цифр, которыми мы пользуемся - десять, 0-1-2-3-4-5-6-7-8-9. Отсчет ведется не с единицы, а с нуля. Для записи чисел больше 9 используются две цифры - 10, 11, 12… для чисел больше 99, три цифры - 100, 101, 102. Такие системы счисления называются позиционными, место цифры в записи числа определяют порядок.

738910 = 7 x 103 + 3 x 102 + 8 x 101 + 9 x 100

Но вернемся к электронике. Цифр всего две, 0 и 1. А, значит, основание системы счисления - 2, условные “десятки”, “сотни” и “тысячи” это степени двойки – 2, 4, 8…

Число 13 в двоичной системе равно 1101. Есть очень простой способ перевода числа в двоичную систему. Делим число на два и записываем остаток от деления2. Это самый младший, правый двоичный разряд. Оставшееся число снова делим на два и полученный остаток от деления размещает слева от уже полученных разрядов числа. И так до тех пор, пока в результате деления не останется 0. А набор нулей и единиц, которые мы записывали справа налево, и будет записью нашего числа в двоичной системе счисления. Попробуйте.

11012 = 1 x 23 + 1 x 22 + 0 x 21 + 1 x 20 = 810 + 410 + 010 + 110 = 1310

Это общий метод для любой позиционной системы счисления, какое число станет основанием системы, на то и надо делить. Если число это меньше 10, то для удобства можно пользоваться теми же арабскими цифрами. Если же больше – придется придумывать новые “цифры”. К примеру, 16-ричная система счисления, тоже довольно распространенная в “компьютерной науке”3, использует 10 арабских цифр и латинские буквы ABCDEF. К примеру, уже упомянутое число 13 в шестнадцатеричной системе счисления записывается одной “цифрой” С, а десятичное 42, легендарный ответ на Главный вопрос жизни, вселенной и всего такого4, выглядит так: 2A.

Виды программного обеспечения#

Традиционно все, что связано с электронно-вычислительной техникой, делят на “твердое” и “мягкое”. К “твердому инвентарю” (буквальный перевод термина “hardware”) относят оборудование – лампы, микросхемы; всё, что можно потрогать. Антитезой к нему введен термин “software”. Под “мягким инвентарем” подразумевается то, что потрогать нельзя – программы в виде электронных импульсов хранятся “где-то внутри”.

Сленговые понятия “железо” и “софт” наиболее близки к исторически сложившимся английским терминам, хотя и не настолько официальны.

Микропрограмма. Компоненты ЭВМ представляют собой “компьютер в компьютере”. Кроме элементной базы – триггеров, регистров, логических схем – в них содержатся еще и программы для работы устройства. Программы эти жестко “зашиты” в микросхемах и выполняют простые вещи – превращение потока импульсов в картинку на экране, передача сигналов от нажатия на клавиши и так далее.

Операционная система. Это “программа программ”. Операционная система обеспечивает взаимодействие с микропрограммами внешних устройств и превращает ЭВМ из набора компонент в единую систему общего назначения.

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

Прикладное программное обеспечение. При помощи всего описанного выше ЭВМ функционирует “сама в себе”. А вот прикладное ПО3 – это “то, ради чего все писалось”4. То, для чего создавались электронно-вычислительные машины. Прикладное ПО касается предметной области – физика, астрономия, системы наблюдения, компьютерная графика, искусственный интеллект, игры, виртуальная реальность, Интернет…

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

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

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

Типы данных#

Все есть число

Слова Пифагора Самосского как нигде применимы в “компьютерной науке”. Электронно-вычислительные машины все свои действия сводят к манипулированию числами. Но что можно представить числами?

Все. Температуру, цвет, звук. Но все многообразие данных невозможно анализировать без определения того, какие операции для них применимы. Нельзя сложить число и геометрическую фигуру, умножить множество на слово и так далее. Для этого данные определяются по типам. А типы определяют действия, которые с ними можно производить.

Числа. Из математики мы знаем, что числа бывают натуральный, целые и дробные. Есть еще комплексные, “но это уже совсем другая история”2. Над числами можно производить математические операции - сложения (+), вычитания (-), умножения (*) и деления (/). Все более сложные операции, такие как извлечение корня, можно свести к этим четырем основным операциям. Десятичные дроби используют в качестве разделителя точку (.) вместо запятой. Все остальное - хорошо нам известно из школьной программы - у операций умножения и деления есть приоритет над операциями сложения и вычитания, скобки используются для определения собственных приоритетов.

(2+2*2-9/(2+1))/3-1

Символы. Все буквы, цифры, знаки препинания и другие символы пронумерованы и составляют таблицу символов. К примеру, заглавная латинская “A” имеет номер 65, строчная - 97, пробел (а это тоже “буква”) записан под номером 32. То есть символ это тоже число. Складывать и перемножать эти числа, конечно, можно - но никакого практического смысла в этом нет. Буквы - это то, из чего состоят слова.

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

Строки. “Привет”, “Мир” - это слова. Слово - это не одна буква, а несколько.

В компьютерном представлении это последовательность символов. Строки можно складывать, но результатом сложения двух цепочек символов будет не побуквенное сложение, а объединение строк в одну “ПриветМир”. А если мы хотим, чтобы пример был осмысленным, то лучше сложить три строки.

a="Привет"
b="Мир" 
c=a+", "+b

Получим фразу “Привет, Мир”, с пробелом после запятой.

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

a[1] = 2
a[3] = 1
b[1] = a[3]
c[0] = a[1] + 2*(b[1]*a[3])

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

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

К примеру, “автомобиль” это структура из переменных “Марка”4, “Модель”, “Цвет”. Машину может характеризовать так же “комплектация”, которая включает в себя вложенные переменные “двигатель”, “навигационная система”. И так далее.

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

Память#

Вся информация, которой оперирует исполнитель, в хранится у него в памяти. Можно сохранить в памяти число (а мы помним, что всё можно записать при помощи чисел), можно его оттуда извлечь. Между этими операциями они хранится в неизменном виде.

Запоминающее устройство на магнитной ленте, которую можно проматывать вперед-назад, последовательно читая и записывая данные, называется памятью последовательного доступа («Sequential Access Memory», «SAM»). Запоминающее устройство из большого количества пронумерованных ячеек, в поторые можно писать напрямую по их «адресам», называется памятью произвольного доступа («Random Access Memory», «RAM»). Память (любого принципа действия), позволяющая только читать однажды записанные данные, называется ROM («Read Only Memory», «память только для чтения»).

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

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

При бесконтрольном создании множества переменных может наступить момент исчерпания доступной памяти - вся она будет занята и создать еще один объект в куче будет невозможно. Эта проблема называется утечкой памяти и во избежание ее нужно проводить «сборку мусора».

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

Базовые алгоритмы#

Как в литературе, по мнению Кристофера Букера, есть только семь основных сюжетов2, так и в программировании базовых алгоритмов всего три. Это те “кубики”, из которых создаются программы.

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

В линейном (последовательном) алгоритме команды выполняются последовательно. Одна за другой, всегда одинаково.

действие 1
действие 2
действие 3

Шаг вперёд-назад, влево-вправо! Шаг вперёд-назад, влево-вправо!

Шаг вперёд-назад! Шаг вперёд-назад! Шаг вперёд-назад!.3

При помощи ветвления можно задать разное поведение программы в разных условиях.

ЕСЛИ условие ТО
    действие
ИНАЧЕ
    другое действие

К сведению: отступы не имеют никакого значения и использованы исключительно для наглядности4.

Условие - это логическое выражение, исчислимая формула. Всю теорию множеств можно уместить в вычисление логических выражений, но нам сейчас важно только то, что результатом этого вычисления будет 1 или 0. В первом случае выполнится “команда”, во втором - “другая_команда”.

Если ясный день - это хорошо,

А когда наоборот - плохо. 5

Циклический алгоритм позволяет выполнять команды многократно. Сколько именно - зависит от условия повторения. В циклах с предусловием сначала проверяется условие, потом выполняется команда. В циклах с постусловием сначала выполняется команда, а потом проверяется условие.

ПОКА 0 ВЫПОЛНЯТЬ действие --> не выполнится
ВЫПОЛНЯТЬ действие ПОКА 0 --> выполнится один раз

Во время исполнения действия условие может измениться. В первом случае на исполнение алгоритма это не повлияет.

– А еще есть “синий цикл”…

– А почему он синий?

– Потому что - до посинения.6

ПОКА 1 ВЫПОЛНЯТЬ действие --> будет выполняться вечно
ВЫПОЛНЯТЬ действие ПОКА 1 --> будет выполняться вечно

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

Декомпозиция#

Буквально слово «декомпозиция» означает «разделение на части». В программировании это означает разделение программы на более простые подпрограммы, а те, в свою очередь, – на еще более простые, пока с одной стороны не окажутся простейшие действия сложения, умножения и вычитания, которые исполнитель способен выполнять без дальнейшего объяснения, а с другой – Deep Blue2 или Mars One3.

Подпрограмма. В самом простом случае, подпрограмма – это несколько действий вместо одного.

ЕСЛИ условие ТО
    НАЧАЛО
        действие 1
        действие 2
        действие 3
    КОНЕЦ
ИНАЧЕ
    другое действие

Процедура. Для именованных подпрограмм используется термин “процедура”. Если мы дадим имя подпрограмме, то тем самым обогатим язык исполнителя новой командой, как если бы она изначально была частью языка исполнителя.

ПРОЦЕДУРА другое действие ЭТО
НАЧАЛО
    действие 42
    действие 16
    действие 28
КОНЕЦ

Функция. В программировании функция имеет схожий смысл со своим математическим аналогом. “Звездочка” (знак *) используется для обозначения арифметической операции умножения

ФУНКЦИЯ квадрат (аргумент) ЭТО
НАЧАЛО
    ВЕРНУТЬ аргумент * аргумент
КОНЕЦ

Функция отличается от процедуры двумя особенностями – она получает аргумент и возвращает результат выполнения.

ЕСЛИ квадрат(2) = 4 ТО
    все в порядке
ИНАЧЕ
    мы в другой вселенной

Рекурсия

“Чтобы понять рекурсию, надо сначала понять рекурсию”4

Рекурсивным называется алгоритм, который обращается к самому себе. Факториал натурального числа есть произведение всех стоящих перед натуральных чисел5. Обобщенная формула факториала N! = (N - 1)! * N.

ФУНКЦИЯ факториал (число) ЭТО
НАЧАЛО
    ЕСЛИ число > 0 ТО
        ВЕРНУТЬ число * факториал (число - 1)
    ИНАЧЕ
        ВЕРНУТЬ 1
КОНЕЦ

Это и есть рекурсия. Обратите внимание – это важно! – на условие выхода (0! = 1). Без него рекурсия ушла бы в бесконечность и алгоритм никогда бы не завершился. При написании рекурсивных алгоритмов всегда надо задавать правильное условие выхода.

Фракталы, задача о Ханойских Башнях - тоже рекурсивные задачи. Существует мнение, что все рекурсивные задачи можно решить и другими способами, но - зачем?!

“Итерация свойственна человеку, рекурсия - божественна”6

Языки программирования#

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

Низкоуровневые языки программирования . Самый низкий уровень программирования – это машинный код, который исполняется непосредственно. По сути набор чисел, которые процессор знает и умеет выполнять. Ассемблер - язык, в котором каждому машинному коду присвоено буквенное обозначение и которое человек уже способен прочесть и понять. Глазами. Хотя уровень абстракций практически нулевой - за каждой командой скрывается машинный код.

Недостаток: зависимость от оборудования, любая замена оборудования – и программу надо будет писать заново. Сфера применимости: программирование контроллеров электронных компонентов, написание унифицированных подпрограмм для систем более высокого уровня.

Языки программирования сверхвысокого уровня . На самом высоком уровне описывается не “как делать”, а “что делать”. В таких языках используются не алгоритмические конструкции, а живой язык. Например, английский. Это уровень искусственного интеллекта.

Недостатки: искусственного интеллекта не существует, языки сверхвысокого уровня недостаточно эффективны. Сфера применимости: пока только научные изыскания в области искусственного интеллекта.

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

Недостатки: невозможно или неэффективно использовать в непрофильной области. Сфера применимости: та, для которой проектировался.

Универсальные языки высокого уровня . Некоторые языки с разной степенью уверенности претендуют на звание универсальных языков. Обычно обучение программированию ведется на одном из таких языков.

Недостатки: менее эффективен, чем специализированные языки. Сфера применимости: везде.

Трансляторы . Языки программирования могут быть любого уровня абстракций, но ЭВМ как работала с машинными кодом, так и работает. Чтобы программы на языках программирования выполнялись, необходимо перевести их в машинный код. Этим занимаются трансляторы.

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

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

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

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

Парадигмы программирования#

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

Императивная. В императивной парадигме программа напоминает последовательность приказов. Это набор команд, последовательно меняющих состояние исполнителя.

Функциональная . В функциональной парадигме программа это функция. И все её структурные составляющие - тоже функции. Главное свойство функции в том, что ее результат зависит только от входных параметров и больше ни от чего. Синус от pi/2 равен 1, а квадратный корень из 4 равен 2. Всегда. Везде. И если эти значения потребуется еще раз, их не потребуется вычислять снова. Достаточно “вспомнить”.

Можно очень сильно увеличить производительность алгоритма за счет отсуствия повторяющихся вычислений. “Это первая выгода”2. Независимые функции можно выполнять одновременно, что позволит распределить программу на несколько исполнителей. “Это вторая выгода”3.

Объектно-ориентированная . Объектно-ориентированная парадигма программирование в двух словах звучит так - “все объекты”. Если все структурные части программы описывать объектами, то программа в целом будет выглядеть некой средой, внутри которой появляются, взаимодействуют между собой и уничтожаются объекты. Взаимодействовать они могут как напрямую, обращаясь к методам друг друга, так и через какой-нибудь объект-супервизор, который занимается получением “событий” и вызовом требуемых методов. Разновидность второго варианта называется событийно-ориентированной концепцией.

И так далее ….

Я намеренно не касаюсь ни “аспектно-”, ни “компонентного-”, ни “еще-чего-то-там-ориентированного” программирования (тысячи их!). Не потому, что это сложно, а - во-первых - потому, что они являются сочетанием уже названных подходов, и - во-вторых - потому, что не все парадигмы программирования “одинаково полезны”. Это теории, которых в любой науке много, которые появляются и исчезают, не оправдав ожиданий, не показав свою полезность и/или применимость и вообще - дело творческое. При желании любую из этих теорий можно найти, изучить, разработать свою и проверять на прочность исследованиями.

Методологии#

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

Waterfall Development . Каскадная разработка (она же “водопад”) делит весь процесс на этапы “анализ - проектирование - реализация - тестирование - интеграция - поддержка”. Это классический подход в промышленной разработке, где аналитики анализируют, архитекторы ставят задачи и так далее. Все начинается с технического задания, которое описывает весь проект в целом и каждую его часть в отдельности. Затем “по написанному” пишется программный код и уходит сначала в тестирование, потом во внедрение и на поддержку.

Iterative and Incremental Development . Итеративная разработка это то же самое, но “маленькими перебежками”. В начале создается “нечто”, что хотя бы смутно напоминает требуемый результат и кое-как работает. Этот “игрушечный” проект называется прототипом. Для него требуется анализ-проектирование-реализация-тестирование, тоже игрушечные, быстрые и дешевые. Это “итерация”. Потом все повторяется, только не с самого начала, а с того места, где закончилась предыдущая итерация. Этот цикл доработок в конечном итоге вырастает в то, что хочет видеть заказчик и - самое главное! - продолжается дальше, до бесконечности адаптируясь к меняющимся реалиям бизнеса и пожеланий заказчика.

Feature-Driven Development . При разработка “от возможностей” прототип выполняет роль “скелета”, на который в ходе каждой итерации добавляется новый функционал.

Test-Driven Development . Разработка на основе тестов - это когда сначала пишутся тесты и весь проект состоит из “заглушек”, которые только и умеют, что эти тесты проходить, а потом они меняются на рабочий код. Новый функционал - это новые тесты и только ПОТОМ новый код. Обычно в реальном проекте тестирование проходит по остаточному принципу и поэтому не всегда на должном уровне. В TDD “покрытие тестами” всегда стопроцентное - это значит, что код всегда проверяем и работает так, как надо. Небольшой бонус - всегда, на любой стадии, у проекта актуальная проектная документация. Собственно, эти два аргумента и есть главное обоснование такого подхода к проектированию.

…и другие

Здесь ситуация обстоит приметно также, как и с парадигмами программирования. Их много, они постоянно появляются и доказывают свою полезность. Или не доказывают и умирают в забвении. Спорные “гибкие методологии” (Agile) очень хорошо выглядят на бумаге и столь же редко внедряются в том виде, в котором задумывались. Есть даже шутливая методология “just write code, motherfucker!”, отражающая все неприятие программистами модных методологий, которые уводят весь процесс от непосредственно программирования в сторону разнообразных организационных “приседаний”.

Итак…#

Вы, наверное, уже догадываетесь.

Писать программы легко. Но программирование - это не написание программ. Это умение думать. У вас есть инструмент, но что вы будете с ними делать? Попробуйте разобраться в игре “крестики-нолики” и напишите программу, которая не проигрывает. А потом возвращайтесь и мы поговорим о деревьях и конечных автоматах.

Программирование - это математика, а не технологические фокусы.


  1. На самом деле, не совсем так, потому что в азбуке Морзе три сигнала — точка, тире и пауза. ↩︎

  2. Если число четное, то это 0; если нечетное – то 1 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  3. Дословный перевод с английского “computer science”, как в англоязычном мире называется информатика ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  4. Дуглас Адамс, “Путеводитель для путешествующих автостопом по галактике” ↩︎ ↩︎ ↩︎ ↩︎ ↩︎

  5. “Если добрый ты…” (песня кота Леопольда), Аркадий Хайт, 1982 ↩︎ ↩︎

  6. Программистский фольклор ↩︎ ↩︎