Грамотное программирование — это парадигма программирования , введенная в 1984 году Дональдом Кнутом , в которой компьютерная программа дается как объяснение того, как она работает, на естественном языке , например английском, с вкраплением (встраиванием) фрагментов макросов и традиционного исходного кода , из которого может быть сгенерирован компилируемый исходный код. [1] Этот подход обычно используется в научных вычислениях и в науке о данных для воспроизводимых исследований и открытого доступа . [2] Грамотные инструменты программирования сегодня используются миллионами программистов. [3]
Парадигма грамотного программирования, задуманная Дональдом Кнутом, представляет собой отход от написания компьютерных программ в том порядке и порядке, который задает компилятор, и вместо этого дает программистам макросы для разработки программ в порядке, требуемом логикой и потоком их мыслей. [4] Грамотные программы пишутся как изложение логики на более естественном языке , в котором макросы используются для сокрытия абстракций и традиционного исходного кода , больше похожего на текст эссе .
Инструменты грамотного программирования (LP) используются для получения двух представлений из исходного файла: одного, понятного компилятору или интерпретатору, «запутанного» кода, а другого для просмотра в виде форматированной документации , которая, как говорят, «соткана» из грамотного программирования. источник. [5] В то время как первое поколение грамотных инструментов программирования было специфичным для компьютерного языка , более поздние не зависят от языка и существуют за пределами отдельных языков программирования.
Грамотное программирование было впервые введено в 1984 году Дональдом Кнутом, который намеревался создавать программы, подходящие для человеческой литературы. Он реализовал его в Стэнфордском университете в рамках своего исследования алгоритмов и цифровой типографики . Реализация была названа « WEB », так как он считал, что это одно из немногих трехбуквенных слов английского языка, которые еще не применялись к вычислительной технике. [6] Однако это напоминает сложную природу программного обеспечения, аккуратно собранного из простых материалов. [1] Практика грамотного программирования значительно возродилась в 2010-х годах с использованием вычислительных ноутбуков , особенно в области науки о данных .
Грамотное программирование — это запись логики программы на человеческом языке с включенными (разделенными примитивной разметкой) фрагментами кода и макросами. Макросы в грамотном исходном файле — это просто похожие на заголовок или пояснительные фразы на человеческом языке, которые описывают человеческие абстракции, созданные при решении задачи программирования и скрывающие фрагменты кода или макросы нижнего уровня. Эти макросы аналогичны алгоритмам псевдокода , которые обычно используются при преподавании информатики . Эти произвольные поясняющие фразы становятся новыми точными операторами, создаваемыми программистом на лету и образующими метаязык поверх основного языка программирования.
Препроцессор используется для замены произвольных иерархий или, скорее, «взаимосвязанных «сетей» макросов» [7] для создания компилируемого исходного кода одной командой («клубок»), а документации — другой («переплетение»). Препроцессор также предоставляет возможность записывать содержимое макросов и добавлять к уже созданным макросам в любое место текста грамотного исходного файла программы, избавляя тем самым от необходимости держать в уме ограничения, налагаемые традиционными языками программирования. или прервать поток мыслей.
По словам Кнута, [8] [9] грамотное программирование обеспечивает более высокое качество программ, поскольку заставляет программистов явно излагать мысли, лежащие в основе программы, делая плохо продуманные проектные решения более очевидными. Кнут также утверждает, что грамотное программирование обеспечивает первоклассную систему документации, которая не является дополнением, а естественным образом вырастает в процессе изложения мыслей во время создания программы. [10] Полученная документация позволяет автору в любой момент возобновить собственный мыслительный процесс, а другим программистам легче понять конструкцию программы. Это отличается от традиционной документации, в которой программисту предоставляется исходный код, следующий порядку, установленному компилятором, и он должен расшифровать мыслительный процесс, лежащий в основе программы, на основе кода и связанных с ним комментариев. Утверждается также, что метаязыковые возможности грамотного программирования облегчают мышление, давая более высокий вид кода «с высоты птичьего полета» и увеличивая количество концепций, которые разум может успешно запомнить и обработать. Применимость этой концепции к программированию в больших масштабах, например к программам коммерческого уровня, подтверждается изданием кода TeX как грамотной программы. [8]
Кнут также утверждает, что грамотное программирование может привести к легкому портированию программного обеспечения в несколько сред, и даже приводит в качестве примера реализацию TeX. [11]
Грамотное программирование очень часто неправильно понимается [12] как относящееся только к форматированной документации, созданной из общего файла с исходным кодом и комментариями (что правильно называется генерацией документации ), или к объемным комментариям, включенным в код. Это обратная сторона грамотного программирования: хорошо документированный код или документация, извлеченная из кода, соответствует структуре кода, а документация встроена в код; в то время как при грамотном программировании код встроен в документацию, причем код соответствует структуре документации.
Это заблуждение привело к утверждениям, что инструменты извлечения комментариев, такие как Perl Plain Old Documentation или системы Java Javadoc , являются «грамотными инструментами программирования». Однако, поскольку эти инструменты не реализуют «сеть абстрактных концепций», скрывающуюся за системой макросов естественного языка, и не предоставляют возможность изменять порядок исходного кода с навязанной машиной последовательности на последовательность, удобную для человеческого разума. , их нельзя назвать грамотными инструментами программирования в том смысле, в каком их имел в виду Кнут. [12] [13]
В 1986 году Джон Бентли попросил Кнута продемонстрировать концепцию грамотного программирования для его колонки Programming Pearls в журнале Communications of the ACM , написав программу в WEB. Кнут прислал ему программу для решения проблемы, ранее обсуждавшейся в колонке (выборка M случайных чисел в диапазоне 1.. N ), а также попросил «задание». Бентли дал ему задачу найти K наиболее распространенных слов в текстовом файле, для чего Кнут написал WEB-программу, которая была опубликована вместе с обзором Дугласа Макилроя из Bell Labs. Макилрой похвалил сложность решения Кнута, его выбор структуры данных (вариант хеш-три Фрэнка М. Ляна ) и презентацию. Он раскритиковал некоторые вопросы стиля, такие как тот факт, что центральная идея была описана в конце статьи, использование магических констант и отсутствие диаграммы, сопровождающей объяснение структуры данных. Макилрой также использовал обзор для критики самой задачи программирования, указав, что в Unix (разработанной в Bell Labs) ранее были написаны утилиты для обработки текста ( tr , sort , uniq и sed ), которые были «основными», и решение это было легко реализовать, отладку и повторное использование можно было получить, объединив эти утилиты в шестистрочном сценарии оболочки . В ответ Бентли написал следующее: [14]
[Макилрой] восхищается исполнением решения, но считает проблему инженерной. (Это, конечно, моя ответственность как постановщика задач; Кнут решил задачу, которую ему поставили, на основаниях, важных для большинства инженеров, — на зарплатах, предоставляемых постановщиками задач.)
Позже Макилрой признал, что его критика была несправедливой, поскольку он критиковал программу Кнута по инженерным соображениям, в то время как целью Кнута было только продемонстрировать грамотную технику программирования. [15] В 1987 году журнал Communications of the ACM опубликовал следующую статью, в которой иллюстрировалось грамотное программирование с помощью программы на языке C, сочетающей художественный подход Кнута с инженерным подходом Макилроя, с критикой Джона Гилберта. [16]
Внедрение грамотного программирования состоит из двух этапов:
Плетение и запутывание выполняются на одном и том же источнике, чтобы они соответствовали друг другу.
Классическим примером грамотного программирования является грамотная реализация стандартной программы подсчета слов Unix wc
. Кнут представил CWEB- версию этого примера в главе 12 своей книги «Грамотное программирование» . Тот же пример позже был переписан для инструмента грамотного программирования Noweb . [17] Этот пример является хорошей иллюстрацией основных элементов грамотного программирования.
Следующий фрагмент грамотной wc
программы [17] показывает, как произвольные описательные фразы на естественном языке используются в грамотной программе для создания макросов, которые действуют как новые «операторы» на грамотном языке программирования и скрывают фрагменты кода или другие макросы. . Обозначение разметки состоит из двойных угловых скобок (" <<...>>
"), которые обозначают макросы, а @
символ " " указывает на конец раздела кода в файле noweb. Символ « <<*>>
» обозначает «корневой», самый верхний узел, с которого грамотный инструмент программирования начнет расширять сеть макросов. Собственно, запись расширенного исходного кода может производиться из любого раздела или подраздела (т.е. фрагмента кода, обозначенного как " <<name of the chunk>>=
", со знаком равенства), поэтому в одном грамотном программном файле может содержаться несколько файлов с машинным исходным кодом.
Целью wc является подсчет строк , слов и / или символов в списке файлов . _ _ _ _ _ _ Количество строк в файле ........ / подробнее / _ _ _ _ _ Вот обзор файла wc . _ _ _ _ _ _ _ c , который определяется программой noweb wc . _ _ nw : <<* >> = << Включаемые заголовочные файлы >> << Определения >> << Глобальные переменные >> << Функции >> << Основная программа >> @ Мы должны включить стандартные определения ввода - вывода , поскольку мы хотим отправлять форматированный вывод на stdout и stderr . _ _ << Включаемые заголовочные файлы >>= #include < stdio.h> @
Распутывание кусков может производиться в любом месте грамотного текстового файла программы, не обязательно в том порядке, в котором они расположены во вмещающем куске, а так, как того требует логика, отраженная в поясняющем тексте, охватывающем всю программу.
Макросы — это не то же самое, что «имена разделов» в стандартной документации. Макросы грамотного программирования скрывают за собой реальный код и могут использоваться внутри любых операторов машинного языка низкого уровня, часто внутри логических операторов, таких как " " if
, " while
" или " case
". Это можно увидеть в следующей wc
грамотной программе. [17]
Нынешний блок , который выполняет подсчет , на самом деле был одним из самых простых в написании . Мы смотрим на каждый символ и меняем состояние , если он начинает или заканчивает слово . << Сканировать файл >>= while ( 1 ) { << Заполнить буфер , если он пуст ; разрыв в конце файла >> c = * ptr ++ ; _ if ( c > ' ' && c < 0177 ) { /* видимые коды ASCII */ if ( ! in_word ) { word_count ++ ; в_слове = 1 ; } продолжать ; } if ( c == '\n' ) line_count ++ ; else if ( c != '' && c != '\t' ) продолжить ; in_word = 0 ; /* c — это новая строка, пробел или табуляция */ } @
Макросы обозначают любой фрагмент кода или другие макросы и являются более общими, чем «фрагментирование» сверху вниз или снизу вверх или подразделение на подразделы. Дональд Кнут сказал, что когда он осознал это, он начал думать о программе как о сети различных частей. [1]
В грамотной программе Noweb, помимо свободного порядка их представления, фрагменты макросов, однажды введенные с помощью " <<...>>=
", могут быть увеличены позже в любом месте файла, просто написав " <<name of the chunk>>=
" и добавив к нему больше контента, как в следующем фрагменте иллюстрирует («плюс» добавляется форматировщиком документа для удобства чтения и отсутствует в коде). [17]
Общие итоги должны быть инициализированы нулем в начале программы.Если бы мы сделали эти переменные локальными по отношению к основной, нам пришлось бы выполнить такую инициализацию.явно; однако глобальные переменные C автоматически обнуляются. (Или, скорее, ``статическиобнулено.» (Понял?) <<Глобальные переменные>>+= длинный tot_word_count, tot_line_count, тот_char_count; /* общее количество слов, строк, символов */ @
Документация к грамотной программе создается в рамках написания программы. Вместо комментариев, предоставляемых в качестве примечаний к исходному коду, грамотная программа содержит объяснение концепций на каждом уровне, при этом концепции более низкого уровня откладываются на соответствующие места, что позволяет лучше передавать мысли. Фрагменты грамотного wc
выше показывают, как переплетаются объяснение программы и ее исходный код. Такое изложение идей создает поток мысли, подобный литературному произведению. Кнут написал «роман», в котором объясняет код интерактивной фантастической игры Colossal Cave Adventure . [18]
Первой опубликованной средой грамотного программирования была WEB , представленная Кнутом в 1981 году для его системы набора текста TeX ; он использует Pascal в качестве основного языка программирования и TeX для набора документации. Полный прокомментированный исходный код TeX был опубликован в книге Кнута TeX: The program , том B его 5-томного издания « Компьютеры и набор текста» . Кнут в частном порядке использовал грамотную систему программирования под названием DOC еще в 1979 году. Его вдохновили идеи Пьера-Арнуля де Марнеффа . [19] Бесплатный CWEB , написанный Кнутом и Сильвио Леви, является WEB-адаптированным для C и C++ , работает на большинстве операционных систем и может создавать документацию TeX и PDF .
Существуют различные другие реализации концепции грамотного программирования, представленные ниже. Многие из новейших из них не имеют макросов и, следовательно, нарушают принцип человеческой логики, что делает их скорее полуграмотными инструментами. Однако они позволяют выполнять код на клеточном уровне, что делает их более похожими на инструменты исследовательского программирования .
Другие полезные инструменты включают в себя:
.hs
и .lhs
; последний означает грамотный Haskell.% здесь текст, описывающий функцию: \begin { code } fact 0 = 1 fact ( n + 1 ) = ( n + 1 ) * fact n \ end { code } здесь еще текст
listings
предоставляет lstlisting
среду, которую можно использовать для украшения исходного кода. Его можно использовать для определения code
среды, которая будет использоваться в Haskell для печати символов следующим образом:\newenvironment { code }{ \lstlistings [language=Haskell] }{ \endlstlistings }\begin { code } comp :: ( бета -> гамма ) -> ( альфа -> бета ) -> ( альфа -> гамма ) ( g ` comp ` f ) x = g ( f x ) \ end { code }
«Макросам WEB разрешено иметь не более одного параметра. Опять же, я сделал это в интересах простоты, потому что заметил, что большинство приложений с несколькими параметрами фактически могут быть сведены к случаю с одним параметром. Например, предположим, что вы хочу определить что-то вроде... Другими словами, имя одного макроса может быть параметром другого макроса. Этот конкретный трюк позволяет..."
- Дональд Э. Кнут , Грамотное программирование [1]
Однако для меня грамотное программирование — это, безусловно, самое важное, что получилось в результате проекта
TeX
. Это не только позволило мне писать и поддерживать программы быстрее и надежнее, чем когда-либо прежде, и было одним из моих величайших источников радости с 1980-х годов, но иногда оно было просто незаменимо. Некоторые из моих основных программ, такие как мета-симулятор MMIX, невозможно было бы написать с использованием какой-либо другой методологии, о которой я когда-либо слышал. Эта сложность была слишком сложной для моего ограниченного мозга; без грамотного программирования все предприятие потерпело бы неудачу. ... Грамотное программирование — это то, что вам нужно, чтобы подняться над обычным уровнем достижений.
«Еще одна удивительная вещь, которую я узнал при использовании WEB, заключалась в том, что традиционные языки программирования заставляли меня писать худшие программы, хотя я не осознавал, что делаю. Моя первоначальная идея заключалась в том, что WEB будет просто инструментом для документирования, но Я действительно обнаружил, что мои WEB-программы лучше, чем программы, которые я писал на других языках».
- Дональд Э. Кнут , Грамотное программирование [1]
«Таким образом, язык WEB позволяет человеку выражать программы в порядке «потока сознания» . TANGLE способен смешать все в структуру, которую требует компилятор PASCAL. Эта особенность WEB, возможно, является его самым большим преимуществом; она делает WEB -написанная программа гораздо читабельнее, чем та же программа, написанная чисто на PASCAL, даже если последняя программа хорошо прокомментирована.И то, что не надо зацикливаться на вопросе сверху вниз или снизу вверх, так как программист теперь я могу рассматривать большую программу как сеть, которую нужно исследовать в психологически правильном порядке, — это, пожалуй, величайший урок, который я извлек из своего недавнего опыта».
- Дональд Э. Кнут , Грамотное программирование [1]
«Я выбрал имя WEB отчасти потому, что это было одно из немногих трехбуквенных слов английского языка, которые еще не применялись к компьютерам. Но со временем я стал чрезвычайно доволен этим именем, потому что думаю, что Сложную часть программного обеспечения действительно лучше всего рассматривать как сеть, искусно собранную из простых материалов. Мы понимаем сложную систему, понимая ее простые части и понимая простые отношения между этими частями и их непосредственными соседями. мы выражаем программу как сеть идей, мы можем подчеркнуть ее структурные свойства естественным и приятным способом».
- Дональд Э. Кнут , Грамотное программирование [1]