Другая эволюция: нули и единицы
Сначала были нули, затем они собрались в буквы, а те — в блоки. Так можно кратко описать эволюцию кода из двух цифр — нуля и единицы,— кода, который сегодня пронизывает все области нашей жизни. Записываетесь ли вы к врачу, звоните ли на горячую линию, оплачиваете ли покупки в магазине — каждый раз вы сталкиваетесь с кодом.
Единый код: начало и первые языки
Идейным прародителем компьютеров считают ткацкий станок Жаккара с перфокартами — пластинами из тонкого картона с отверстиями, позволяющими пройти лишь некоторым иглам. Однако все использовавшие этот принцип аппараты выполняли задачи только одного типа. Пока в 1834 году Чарльз Бэббидж не начал работу над «аналитической машиной» — устройством, способным совершать несколько видов операций. К сожалению, Бэббидж не успел завершить начатое. Вместо него это сделала работавшая с ним графиня Лавлейс. Она поняла, что наличие или отсутствие отверстий в картонке может выражать не только числа, но и узоры, музыку, буквы.
Компьютер мыслит двоично — как в азбуке Морзе: точка — нуль, тире — единица. Либо есть заряд (лампочка горит), либо его нет (лампочка потухла). Таким образом, код — это лишь упорядоченная последовательность зарядов и их отсутствия. В такой трактовке логические операции очень просты: «И» — наличие двух сигналов, «ИЛИ» — хотя бы одного из них. Код устроен аналогично тому, как все живые существа в основном состоят из комбинаций четырех биогенных элементов: С, O, N, H.
В 40-х годах XX века программы вводили с помощью электромеханических переключателей, позже — перфолент. Данные для обработки брались с перфокарт, а результаты вычислений выводили электрические печатные машины. В ходе работы с первым программно-управляемым компьютером Mark I специалисты ввели понятие подпрограмм — многократно используемых функциональных последовательностей кода, из которых можно компоновать полноценный алгоритм.
В 1949 году возник первый язык программирования — Assembler. Его команды буквально соответствуют командам машины или их последовательностям. Мы никуда не ушли от нулей и единиц, а лишь абстрагировали их в более понятные субъединицы, мнемонические имена — буквы и цифры, — как выстроившиеся в молекулы атомы. Компьютер не понимает ничего, кроме электрических сигналов, но разработчики сделали так, чтобы было удобнее нам: ряду нулей-единиц присвоили абстрактное «имя», которое программа при запуске переводит обратно в сигналы.
В 50-х годах XX века компьютерные системы чаще всего устанавливали в университетах, где они пользовались большим спросом. Тогда же появились ассемблеровские языки, однако это не упростило программирование: компиляторы были очень чувствительны к ошибкам в синтаксисе и структуре кода. Ошибка программиста дорого стоила — чтобы получить доступ к компилятору, приходилось занимать очередь за пару недель.
Возросший в 60-х годах XX века интерес к компьютерам и программированию стал причиной возникновения нового подхода к созданию языков— коллективного. Появилась необходимость стандартизировать старую и новую информацию, чтобы избежать повторений. Теперь программированию обучали повсеместно— больше не нужно быть инженером, чтобы понимать, как машина работает с написанным для нее текстом. Позволили это сделать образовательные языки— BASIC и Logo.
Если до 70-х годов XX века кодинг был доступен в основном студентам и специалистам, а новые языки программирования придумывали комитеты и коммерческие компании, то с появлением ПК программирование стало достоянием общественности. Борьба за доминирование между BASIC и Pascal привела к появлению диалекта Turbo Pascal, который сегодня изучают во многих российских школах.
Только в 80-х годах XX века разработчики перестали задумываться о технических характеристиках того или иного компьютера. Это привело к развитию идей объектно-ориентированного программирования (ООП). Раньше, если бы мы захотели запрограммировать, условно, автомобиль, нам бы пришлось писать код для каждой отдельной машины. Теперь можно задать программу как модуль, имеющий меняющиеся от модели к модели элементы (переменные, функции).
Единый код: высокоуровневые языки
Однако ввод информации все равно вызывал трудности. Люди стали использовать повседневные глаголы: run, remember, stop и прочее. Так появились высокоуровневые языки программирования: Basic, Java, C, C++, Python, Perl и другие. Так же, как и человеческие языки, они передают одну мысль компьютеру разными словами: как cat и «кошка» обозначают одно и то же животное. К тому же, языки имеют и функциональные различия: одни чаще используют для написания чего-то сложноструктурированного (Java), другие — для веб-программирования (Python).
Первый графический интерфейс пользователя (ГИП) представила команда программистов из НИЦ Xerox PARC в 1973 году. Сегодня ГИП достиг такого уровня, что стало возможным программировать, не написав ни слова: просто перемещай графические объекты и строй алгоритм в визуальных средах программирования (Visual Studio, Sketchware и прочие). Подобно тому, как молекулы организуются в мембраны, клетки и ткани, функциональные блоки собираются в программы. В основе все так же две цифры (или атомы всего четырех элементов), а блок (молекула) — их последовательность, определяющая функции.
Языки программирования придумывают и в качестве произведения искусства, и чтобы найти границы авторских возможностей или реализовать некую идею, а иногда и в шутку.
Единый код: следующий виток
Сегодня человечество программирует на принципиально новом уровне. Мы задаем машине входные (предикторы) и выходные (отклики) данные, и она уже сама пишет для себя команды, объединяя их в алгоритм. Например, вы показываете компьютеру множество фотографий кошек, среди которых попадаются изображения собак. Вы будто сидите с ним, как с ребенком, и говорите: «Это кошка. Это кошка. А это нет». Компьютер, исходя из ваших слов, строит оптимальную классификацию изображений. Это машинное обучение, принцип искусственного интеллекта. И если вас до сих пор удивляют автоматизированные переводчики, то в них нет ничего магического: машина все так же пишет команды из нулей и единиц, только самостоятельно.
Таким образом, обучение компьютера можно сравнить с обучением маленьких детей. Младенец слышит длинный набор звуков и повторяющиеся сочетания в нем: например, «ма-ма» и «па-па». Он замечает их в определенных местах в предложениях, в определенной обстановке и при определенном сочетании других событий. Ребенок понимает, что это единое слово и у него есть значение. Так мы учимся языку, его образам и понятиям. То же делает и машина.
Когда-то Google Translate содержал в себе более миллиона строк кода — более миллиона крохотных команд, написанных человеком. Сегодня их количество уменьшилось примерно в две тысячи раз. И все это благодаря переходу на машинное обучение, при котором программа учится на каждом новом запросе.
Принцип машинного обучения постепенно внедряют во многие сферы жизни: диагностика в медицине, беспилотное управление транспортом, распознавание лиц в пунктах контроля, судебная экспертиза и прочее. На программиста накладывается ответственность: его код должен учитывать огромное количество переменных — обстоятельств. Поэтому важно, чтобы над созданием нового продукта работала команда, состоящая из совсем непохожих людей. Ведь чем более разнообразный опыт «учителя» мы дадим компьютеру, тем гибче и умнее он станет.
Эпоха ПК: калькуляторы и энтузиасты
Первые персональные компьютеры (ПК) собирали энтузиасты, недовольные невозможностью программировать в любое время и в любом месте. Однако сборка «домашнего» компьютера требовала навыков пайки и написания машинного кода: программное обеспечение в то время было продуктом штучным и не всегда доступным. Коммерческие лидеры всерьез идею ПК не восприняли из-за ограниченных возможностей ввода-вывода, нехватки стандартизации, узости применения и высоких требований к пользователю.
Примечательно, что первым бизнес контрактом компании Intel Corporation, которую основали авторы первого транзистора, было создание чипов для настольных калькуляторов. Впоследствии разработчики компании выпустили микропроцессор Intel 4004 ставший основой будущих ПК.
Первые массовые ПК имели всего 4 Кб памяти, позднее — 16 Кб. Компиляторы многих языков занимали сотни килобайт, в отличие от BASIC, в связи с чем он получил широкое распространение.
За последние 20 лет ООП начало сдавать позиции, а молодые языки (Go, Rust и Swift) все чаще используют абстрактный тип данных — типажи. Расширился набор инструментов: помимо компилятора и отладчика появились линтеры (создание и поддержка информационных сетей), шаблонизаторы (использование шаблонов для создания html-страниц) и средства автоматического форматирования кода. Если раньше для каждого отдельного языка разрабатывали свою среду (Integrated Development Environment, IDE), то современный редактор исходного кода Visual Studio Code поддерживает более 30 совершенно разных языков. А вот создание новых языков программирования теперь еще и хобби.
Иллюстрации: wikipedia.org; bbc.co.uk
На обложке — IBM PC (IBM 5150)
Материал опубликован в журнале NewTone