Этим летом мне на глаза попалось эссе Брайана Кернигана «Иногда старые способы — лучшие», опубликованное в честь 25-летнего юбилея журнала IEEE Software в 2008 году. В нем профессор Керниган рассказывал о том, какие инструменты он использует в работе.
В тот момент он был занят двумя сложными проектами — один из них подразумевал экспертный анализ проекта на 100 000 строк кода, написанный на C и Assembler в 1990 году, под Windows XP; другой — перенос кода с экзотического языка L1 на не менее экзотический язык L2 при помощи программы, написанной на неназванном скриптовом языке под Linux. Удивительно, но для столь разных задач профессор Керниган вместо IDE использовал один и тот же набор инструментов — grep, diff, sort, awk, wc и прочих «старых знакомых» из эпохи раннего Unix. Более того, многие инструменты и IDE конца прошлого десятилетия он подверг критике за неудобность и несовершенство.
Действительно, к некоторым вещам в своей жизни мы привыкли настолько сильно, что уже воспринимаем их за данность и критиковать их нам даже не приходит в голову — нам кажется, будто они существовали всегда. Подобный образ мышления помогает адаптироваться к потоку новой информации и неизбежен в современном мире, но давайте не будем сегодня отказывать себе в удовольствии «спуститься на уровень ниже», чтобы увидеть, как появилась сама идея программных инструментов (они же далее по тексту — «software tools», утилиты, команды Unix).
Те, кто
Конечно же, началось всё в стенах лаборатории Bell Labs, принадлежащей AT&T — именно здесь появились на свет Unix, C и (несколько позже) С++. Поскольку появление команд Unix было неразрывно связано с созданием самой ОС, основные действующие лица здесь — хорошо знакомые читателям Хабрахабра Кен Томпсон, Брайан Керниган и Альфред Ахо.
Кен Томпсон, став вместе с Деннисом Ритчи создателем Unix, в 1975 году покинет Bell Labs и вернется в свою альма-матер, университет Беркли, где поспособствует появлению BSD; позже он вернется в Bell Labs, где вместе с Робом Пайком и остальными займется работой над Plan 9.
Альфред Ахо известен отечественным программистам по знаменитой «Книге дракона» (она же — «Компиляторы: принципы, технологии и инструменты»), а также по учебнику «Структуры данных и алгоритмы». Ахо проработал в Bell Labs c 1967 года по 1991, после чего еще раз вернулся туда в роли вице-президента исследовательского центра Computer Science на рубеже тысячелетий.
Брайан Керниган, соавтор знаменитой книги-на-все-времена K&R C Programming Language (он скрывается под буквой «K» из K&R), а также соавтор немалого количества других замечательных книг по программированию, опубликованных за последние тридцать лет — включая недавнюю Go Programming Language.
Керниган начал свою карьеру в 1966 году в MIT, где имел косвенное отношение к проекту Multics. Год спустя, во время аспирантуры в университете Принстон, он становится сотрудником Bell Labs, а в 1969 году — одним из первых разработчиков, принявших участие в работе над Unix. Кернигану был присвоен user ID #9, но первый его заметный вклад в Unix относится к 1973 году — это создание eqn, препроцессора troff для языка описания математических выражений.
Утверждается, что это — самый первый «Hello World» в мире. Написал его Брайан Керниган. (источник)
Для этих и многих других ученых, трудившихся в Bell Labs конца 60-ых — начала 70-ых, Unix был гораздо большим, чем просто очередной ОС.
Software Tools
Сегодня мы воспринимаем идею команд и конвейеров Unix как нечто само собой разумеющееся; однако, в действительности так было далеко не всегда.
Сама идея того, что для повышения продуктивности программистов следует использовать инструменты — аналогичные тому, что человечество использовало в других областях своей жизни — конечно же не нова. Еще один из пионеров computer science Алан Джей Перлис прогнозировал, что появление большого количества подручных инструментов сможет позволить программистами создавать гораздо более масштабные проекты.
Первым реальным шагом в этом направлении стало изобретение систем разделения времени, которая позволяла распределять вычислительные ресурсы среди многих пользователей. Вторым — создание Multics, попытка реализации подобной системы. Третьим — Unix, выросшая на обломках Multics.
В 70-ых за пределами Bell Labs и операционной системы Unix идея создания подобных инструментов была неизвестна. Зато авторы Unix прекрасно понимали, с чем имеют дело — ведь для них ключевой чертой Unix была гибкость; при желании, из простой ОС Unix превращался в полноценную IDE. Причем, само собой разумеется, эта идея остается применима и сегодня (см. статью «Unix как IDE»).
Заложенная в системе Unix гибкость позволяла взглянуть на само программирование по-новому. «Вам нужна данная функция? У нас ее нет, но благодаря утилитам #1 и #2, мы можем реализовать её прямо сейчас, и завтра вы сможете ею пользоваться». В те годы, когда «гибких» методологий разработки программного обеспечения на практике не использовалось, и задачи могли занимать месяцы, подобные слова дорогого стоили.
Мало кто знает, что конвейер (pipe), одна из важнейших особенностей Unix, могли бы стать частью данной ОС еще в 1969 году. Тогда идея, подобная этой, рассматривалась Ритчи и Томпсоном при проектировании файловой системы, но, увы, «воображение подвело их», о чем впоследствии сокрушался Ричи. Зато не подвёл начальник Исследовательского отдела Bell Labs Дуглас Макилрой, который придумал и описал данный концепт в man pages в Unix v3.
После того, как 15 января 1973 года в Unix впервые появляются каналы, это не только «выводит из строя» всю Bell Labs («На следующий день после того, как мы реализовали pipes, каждый посчитал своим долгом попробовать написать однострочник» — будет вспоминать позже Макилрой), но и дает мощнейший финальный толчок, необходимый для реализации идеи программных инструментов, которые можно было бы комбинировать.
Следующим на свет появится grep, после которого станет окончательно ясно — за этой идеей стоит будущее. Сформулирована она будет в знаменитой «Философии UNIX»:
Пусть каждая программа делает всего одно дело, но делает его хорошо. Если нужно выполнить новую функцию, лучше сделать новую программу, чем запутывать старую добавлением новых «фич». Используйте инструменты, чтобы облегчить свою задачу себе и другим, даже если для этого вам надо написать новые вспомогательные утилиты, которые потом придется выбросить.
GREP
grep долгое время был личным инструментом Кена Томпсона; первая публичная версия grep вошла в состав Unix v4 — и сразу же стала для всех остальных инструментом, востребованным в ежедневной работе.
Само название grep сегодня часто расшифровывают как general regular expression parser; однако, по утверждениям Денниса Ритчи и Кена Томпсона, название утилиты появилось другим образом: в редакторах qed/ed, g/re/p было всего лишь командой редактора, которую оно выполняло — global regular expression print (глобальный поиск регулярного выражения и напечатать строки, содержащих совпадения).
Дуглас Макилрой, автор spell, diff, sort, join и других команд, впоследствии будет утверждать, что grep был добавлен по его просьбе. Он занимался синтезатором речи, и ему нужно было, чтобы Кен Томпсон «вынес» наружу из редактора ed функционал поиска регулярок в тексте в отдельную программу. Увы, неизвестно, насколько это является правдой.
В любом случае, grep стал отправной точкой для всех остальных software tools — после него Bell Labs стала двигаться в направлении разработки различных инструментов, которые можно было бы комбинировать между собой. Однако, в директорию с утилитами попадало далеко не всё; среди разработчиков существовала договоренность о том, чтобы воздерживаться от любого ненужного «мусора». Поэтому, прежде чем команды могли попасть в публичный доступ, они чаще всего проходили долгую обкатку в приватном режиме.
Кроме того, авторы Unix нигде не фиксировали время создания той или иной команды, поэтому нам остается ориентироваться по датам, указанным в man — моменту, когда та или иная команда появилась в справочном руководстве.
Когда в 1975 году Брайан Керниган и Билл Плагер выпустят книгу Software Tools, она познакомит с идеей программ-инструментов широкую аудиторию. Позаимствовав идею у Unix, данная книга продемонстрировала, как при помощи небольшого набора текстовых утилит можно сделать программистов гораздо более продуктивными. Интересный факт: программы в этой книге написаны на диалекте Fortran — поскольку на тот момент C едва исполнилось три года, авторы сделали ставку на Fortran, надеясь благодаря этому продать побольше копий.
Несмотря на то, что словосочетание «software tools» до выхода книги в стенах Bell Labs не употреблялось, трудно сказать, кому принадлежало авторство этой концепции. Тот же Керниган наотрез отказывается признавать себя автором этой идеи; он скорее считает себя популяризатором данного подхода, и с этим трудно поспорить — начиная с eqn и многочисленных руководств по Unix, написанным им в 70-ых, он занимался продвижением этой идеи в массы.
Спустя два года, Керниган станет автором еще одной утилиты (а точнее — языка), которая до сих пор продолжает верой и правдой служить программистам — awk.
AWK
AWK был рожден из-за необходимости. Никто и никогда не думал, что он будет использоваться за пределами группы нескольких программистов, трудящихся в Bell Labs. Альфреду Ахо, который тогда работал в Bell Labs, приходилось следить за бюджетами, корреспонденцией — и за оценками студентов университета, который был расположен поблизости и в котором он в те годы преподавал.
Конечно же, оптимальным способом решения этих задач было бы написание программ длиной в одну-две строки; вот только языка, на котором такие программы можно было бы написать, тогда не существовало. В те годы, в соседнем с Ахо кабинете работал Брайан Керниган, и у того собственные рутинные задачи вызывали аналогичное желание. Каждый день они обсуждали эти идеи снова и снова, что в результате привело их к желанию вместе создать язык для pattern-matching (сопоставление с образцом), который подходил бы для простых задач по обработке данных.
Источником вдохновения для AWK выступил именно grep. Но если всё, что умел GREP, было поиском в файле совпадений с достаточно ограниченным классом регулярных выражений и печать всех найденных строк, то авторам AWK хотелось большего. Во-первых, программа должна была работать с числами и строками; во-вторых, позволять больше разнообразных действий по обработке данных, а не только простой вывод строк на печать.
Ахо и Керниган к тому моменту достаточно долго занимались алгоритмами, связанными обработкой данных. Для Ахо эти задачи представляли особый интерес; поэтому он обратил внимание на LEX и YACC, которые использовались в Bell Labs для создания компиляторов (лишь позже они начнут применяться и в других местах). С этими программами был знаком и Брайан Керниган, поэтому такие вещи, как использование лексем, стали для AWK само собой разумеющимися.
Питер Вайнбергер был в курсе происходящего с самого начала. Он присоединился к Ахо и Кернигану в тот момент, когда они закончили со спецификацией грамматики, и за неделю создал рабочий прототип. Благодаря его работе стало возможным дальше заниматься эволюцией языка.
Лишь только на то, чтобы договориться, какие конструкции должны быть в языке, а какие — нет, ушел целый год. Самая первая версия AWK была написана в конце 1977 года. Название программному средству и языку пришло само собой — из-за того, что троицу постоянно видели вместе, коллеги успели привыкнуть к ним обращаться как к «AWK» (по первым инициалам фамилий)!
Созданный язык получился настолько удачным, что привлек в ряды программистов тех, кто раньше о программировании и не помышлял. Ахо позже вспоминал, что встречал людей, которые делали абсолютно умопомрачительные проекты при помощи AWK — например, один энтузиаст реализовал на нём собственный CAD (САПР) и сокрушался о том, что из-за бага в AWK он потерял три недели своего времени. (Кстати, после этой жалобы Ахо и Керниган решили, что пора внедрять контроль качества, и с тех пор прежде чем реализовывать в AWK новый функционал, разработчик должен был сначала написать для него тест)
Past & Present
Инструменты, которыми медленно обрастал Unix, привлекали к ОС внимание все более широкой аудитории. Их можно было быстро изучить и удобно использовать, каждый раз экономя время на доселе трудновыполнимых задачах.
Изучить awk и сегодня не составляет особой сложности. Этот репозиторий на Github, посвященный обработке текста из командной строки, предлагает сотни примеров программ на awk и grep. Не забудьте также почитать про xargs, который используется для параллельного запуска нескольких процессов.
Если вам нужно более основательно подойти к вопросу, то к вашим услугам — The GNU Awk User’s Guide, крайне подробный справочник, который отлично подойдет в качестве учебника.
Если же вы загорелись идеей посмотреть, как выглядел исходный код awk в разные годы, то вас ждет приятный сюрприз. Dan Bornstein, создатель Dalvik, собрал в своем репозитории все версии «той самой» One True Awk, какие только смог найти! В репозитории хранится исключительно оригинальная awk, которую написал и активно поддерживал впоследствии Брайан Керниган — поэтому ее часто называют bwk.
Если так глубоко «нырять» вам не хочется — можете посмотреть на рабочие исходники bwk в другом репозитории.
Идея «software tools» продолжит набирать обороты. К 1981 году в состав самой только Unix входило уже более 300 утилит. AWK тоже не пропадет бесследно — он долго будет оставаться одним из самых популярных языков и вдохновит своими принципами Perl.
По его же словам, с того времени утекло много воды — набрали свою популярность Java и Python, которые предложили программистам свою выразительность и безопасность в обмен на время и память, что в наши дни часто оказывается доступным компромиссом.
Эпилог
Возвращаясь к началу нашего разговора, после прочтения эссе я решил задать вопрос профессору Кернигану — как изменился его рабочий процесс за последние десять лет, и чем сегодня он пользуется в своей работе? Ответ мне показался достаточно интересным:
С той поры немногое изменилось. Я по большей части использую sam и vi для редактирования текста. Именно их я использовал для книги про Go; Алан Донован — волшебник emacs («emacs wizard»). Среди тех, кто пишет на Go в NY, я редко встречал кого-то, кто бы пользовался полноценной IDE — и не уверен, что вообще встречал таких людей.
Что ещё изменилось? Сегодня я пожалуй пишу гораздо больше кода на Python, чем 10 лет назад. Он лучше масштабируется, чем AWK; впрочем, не то чтобы мне приходится писать большие программы.
Brian K
На работе Брайан по-прежнему использует 27-дюймовый iMac, а дома у него — несколько MacBook Pro и MacBook Air; старый Lenovo с установленной Windows XP. «Маки» требуются по большей части как терминалы для доступа к Linux-серверам университета, в котором он работает.
Для чтения почты профессор Керниган по-прежнему использует Alpine, в качестве редактора — Sam, написанный Робом Пайком, и vi, который очень хорошо знает (каждый раз, когда он подступается к emacs, все равно что-то мешает привыкнуть), а больше всего мечтает избавиться от невообразимого количества проводов и коннекторов, которые досаждают дома и в поездках. Если вас интересует больше подробностей, то небольшое интервью по этой теме он давал здесь — хотя оно уже и успело устареть на 4 года, не так многое изменилось с тех пор.
Вот так идеи, появившиеся полвека назад, продолжают служить нам и сегодня; остается надеяться, что и современное нам ПО найдет своё место в будущем.
Tortortor
«Не забудьте также почитать про xargs, который используется для параллельного запуска нескольких процессов.»
точно-точно?
powerman
Точно-точно.
-P max-procs
удобная штука.