Разработка

На примере программы «Жизнь» обсудим общий подход к программированию, применяемый повсеместно, можно сказать, технологию — метод декомпозиции (пошаговой детализации). Суть этой технологии заключается в том, что исходную задачу программист сводит к нескольким другим, более частным, специальным задачам (подзадачам). Те, в свою очередь также сводятся нескольким подзадачам и так далее. Каждое такое действие — шаг декомпозиции. Процедурные языки, к которым относится и Perl, очень хорошо поддерживают технику декомпозиции, поскольку для каждой задачи/подзадачи можно запрограммировать процедуру, решающую её.

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

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

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

В-третьих, программирование с использованием метода декомпозиции приводит к более ясным для понимания программам. Особенно если программист даёт переменным и процедурам «говорящие» имена, из которых понятно их предназначение. Конечно, понять, что делает процедура xxx, или для чего создавалась переменная z80, невозможно. Другое дело переменная lineCount или процедура drawTriangle. Ясная и выдержанная в едином стиле номенклатура переменных и процедур — важная обязанность программиста; те, кто позволяет себе давать имена вроде xxx или z80, профнепригодны.

[Четвёртая выгода — топологическая: команды, относящиеся к решению определённой программы. Хорошо, если тело процедуры помещается на экране редактора целиком — пара десятков строчек].

Приступим к разработке программы, применяя метод декомпозиции.

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

Логично было бы действия, выполняемые однократно в начале работы, объединить в процедуру init (от initiate, начинать). Однократные действия в конце работы — в процедуру term (от terminate, завершить). Процедуру, где перебираются все клетки поля и выясняется их дальнейшая судьба, назовём step (шаг). И, наконец, отрисовкой экрана займётся процедура frame (кадр).

Таким образом, первый шаг декомпозиции даёт следующий грубый набросок будущей программы:

# Декларативная часть программы —
# объявления и определения процедур

sub init {  }
sub term {  }
sub step {  }
sub frame {  }

# Исполняемая часть программы

init;

while(1)
{
	step;
	frame;
}

Информатика-54© А. Н. Швец