По большей части автоматное программирование связано с понятием "конечный автомат". Не вдаваясь в математические дебри, конечный автомат можно определить следующим образом:
Модель, с помощью которой удобно представлять процесс, имеющий конечное число дискретных управляющих состояний.
В первую очередь необходимо обратить внимание на то, что finite-state machine появляется только там, где есть процесс. Возьмём пример с Хекслета. Сущность "курс" участвует в процессе публикации на сайте. Сначала курс не виден, но потом мы его публикуем, и он становится доступным на сайте. При этом, у нас есть возможность произвести обратное действие. Этот же курс участвует и в другом процессе, который можно назвать "завершённость". Наши курсы могут появляться на сайте до того, как мы их запишем до конца. В какой-то момент курс наполняется всеми уроками, и мы переводим конечный автомат в положение "завершён". Получается, что одна и та же сущность участвует, как минимум, в двух процессах. И каждый обладает своим собственным конечным автоматом.
Второе, что мы видим в этом определении: слово "состояние". Состояние — основа любого конечного автомата, и по жизни мы периодически пользуемся этим понятием. Тот смысл, который закладывается в него на интуитивном уровне, идентичен смыслу, который закладывается в него при работе с конечными автоматами. Например, человек бывает сытым или голодным, спящим, болеющим и даже, прости господи, мертвым. А вода бывает жидкой, твёрдой (лёд) и газообразной. Это всё состояния разных процессов.
В определении уточняется, что состояния должны быть дискретными. Другими словами, мы должны иметь возможность проводить чёткие различия между разными состояниями процесса. Процесс нагрева воды нельзя представить как конечный автомат, если мы не выделим в нём конкретные точки (состояния): например, тёплая вода (50 градусов), горячая вода (80 градусов) и холодная вода (10 градусов).
И последнее. Что значит "управляющие состояния"? Понятие состояния не является чужеродным для мира программирования. В одной из первых лекций я рассказывал о том, что состояние программы это, грубо говоря, слепок её памяти. Другими словами, значение всех переменных в конкретный момент времени. Это действительно так, но можно пойти ещё дальше и заметить, что состояние можно поделить на два типа. Первый тип — это состояние, отвечающее за все возможные пути движения данных сквозь программу. Второй — это данные сами по себе или так называемое вычислительное состояние.
Если взять тот же пример с курсом, то мы увидим, что в нём, с одной стороны, присутствует управляющее состояние, отвечающее за видимость курса на сайте, с другой стороны, курс наполнен количественными переменными состояниями, такими как количество уроков, ссылки на видео, тексты и квизы.
Управляющие состояния | Вычислительные состояния |
---|---|
Их число не очень велико | Их число либо бесконечно, либо конечно, но очень велико |
Каждое из них имеет вполне определённый смысл и качественно отличается от других | Большинство из них не имеет смысла и отличается от остальных лишь количественно |
Они определяют действия, которые совершает сущность | Они непосредственно определяют лишь результаты действий |
Рассмотрим простейший конечный автомат на примере телевизора и процесса включения. В этом процессе участвуют два состояния "включен" и "выключен", которые меняются по событиям "включить" и "выключить".
Выше видно так называемую диаграмму состояний. Это графическое отображение, помогающее визуально представить себе схему переходов между состояниями и увидеть все ограничения системы (не из всех состояний можно перейти во все). Как видите, с телевизором всё достаточно просто и интуитивно понятно. Давайте взглянем на более интересный пример:
Этот автомат описывает процесс приготовления кофе в кофемашине. Не так тривиально как с телевизором.
Что ещё может быть описано конечным автоматом?
- Состояние заказа
- Светофор
- Активация Сим-карты
- Запуск практики на Хекслете
- Пользовательские интерфейсы (UI)
Лично мне кажется, что проще перечислить то, что не описывается конечным автоматом, чем наоборот.
Вывод
Реальный мир полон процессов, которые описываются конечными автоматами. Другими словами, конечные автоматы всегда присутствуют независимо от того, знаем мы про них или нет.
Акцентирую на этом ваше внимание. В моей практике часто встречается убеждение у уже опытных программистов, что конечные автоматы усложняют жизнь и/или они нужны только для написания компиляторов. Это большое заблуждение, вызванное отсутствием должной базовой подготовки. Если в вашей программе есть сущность со сложным поведением, то по определению самым простым способом описания её процессов является конечный автомат.
Распознать сущность со сложным поведением в исходном коде программы можно следующим образом: при традиционной реализации таких сущностей используются логические переменные, называемые флагами, и многочисленные запутанные конструкции ветвления, условиями в которых выступают различные комбинации значений флагов. Такой способ описания логики сложного поведения плохо структурирован, труден для понимания и модификации, подвержен ошибкам.
Одна из центральных идей автоматного программирования состоит в отделении описания логики поведения (при каких условиях необходимо выполнить те или иные действия) от описания его семантики (собственно смысла каждого из действий). Кроме того, описание логики при автоматном подходе жестко структурировано. Эти свойства делают автоматное описание сложного поведения наглядным и ясным.
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты