Tuesday 12 October 2010

Литуратурная аппаратура на VHDL

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

Сперва о инструментарии, который мною использовался. Это была реализация системы литературного программирования noweb, которая не привязана ни к какому языку программирования (что оказалось крайне приятным, так как VHDL специально никто ничего подобного не делал). В качестве редактора использовался emacs + noweb.el. Текстовая часть кода оформлялась в LaTeX (тут была альтернатива в качестве html). В принципе, эти инструменты позволили с комфортом работать над задачей, после некоторой привычки. К сожалению, noweb.el является достаточно кривой реализацией, с некоторым количеством неприятных моментов (часто слетает подсветка синтаксиса).

Русская вики даёт следующее определение для литературного программирования:

Литературное (английский термин намеренно двусмысленный), или грамотное программирование (англ. Literate Programming) — концепция, методология программирования и документирования. Термин и саму концепцию разработал Дональд Кнут в 1981 году при разработке системы компьютерной вёрстки TeX.

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

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

<<фича такая-то>>=
Код этой фичи, абсолютно выдранный из контекста.
@

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

<<имя_файла>>=
Заголовок такой-то
<<контескт такой-то фичи>>
<<фича такая-то>>
<<фича такая-то>>
<<фича такая-то>>
Ещё какой-то код, необходимый тут.
@

Теперь, мы можем двумя простыми командами получить как статью, в которой довольно неплохо описано, что делает программа (noweave -delay programm.nw > text.tex) и собственно сам код программы (notangle -Rимя_файла programm.nwп > имя_файла). Так как вы нормальный человек, а следовательно не достаточно внимательны, команда для кода скорее всего любезно скажет вам, какие аспекты программы вы забыли, и вы будете вынуждены, добавить пару абзацев текста.

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

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

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

Недостатки:
- Не понятно как это можно применять для динамических языков, таких как Smalltalk и Lisp.
- Затруднена разработка по чуть-чуть, постоянно тестируя, хотя как мне кажется данный недостаток слегка надуман в данном случае.
- Не совсем понятно, как такой стиль может применяться в коллективе, так как все думают по разному.
- (самый существенный, также его отмечает Кнут) Мало уметь программировать, надо уметь и писать. 

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

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

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