Проектирование конечного автомата на C++

У меня есть небольшая проблема, связанная с моделированием государственной машины.

мне удалось сделать немного инженерии знаний и "обратного инженера" набор примитивных детерминированных правил, которые определяют состояние, а также переходы состояний.

Я хотел бы знать, что лучшие практики в отношении:

  • Как строго проверить мои состояния и переходы состояний, чтобы убедиться, что система не может оказаться в неопределенном государство.

  • Как обеспечить выполнение требований перехода состояния (например, должно быть невозможно перейти непосредственно из stateFoo в StateFooBar, т. е. наполнить каждое состояние "знаниями" о состояниях, в которые оно может перейти.

В идеале, я хотел бы использовать чистый, основанный на шаблонах дизайн, с шаблонами везде, где это возможно.

Мне нужно где-то начать, и я был бы благодарен за любые указатели (без каламбура), которые послали мою сторону.

7 ответов


обязательно посмотри Повысить Библиотеку Statechart.


Гоша, это не так сложно, как кажется. Код State machine очень прост и короток.

сохраните состояние в переменной, скажем myState.

машина состояния будет оператором switch, ветвящимся на значение переменной myState для выполнения кода для каждого состояния.

код будет полон таких строк:

myState = newState;

чтобы применить требования перехода состояния, вам нужно добавить небольшой метод, называемый вместо этого, например это

void DoSafeStateTransition( int newState )
{
// check myState -. newState is not forbidden
// lots of ways to do this
// perhaps nested switch statement

switch( myState ) {

 …

case X:  switch( newState ) 
    case A: case B:  case Z: HorribleError( newState );
    break;

 ...

}

// check that newState is not undetermined

switch( newState ) {

// all the determined states
case A: case B: case C … case Z: myState = newState; break;
default: HorribleError( newState );
}
}
void HorribleError( int newState )
{  printf("Attempt to go from %d to %d - disallowed\n",
       myState, newState );
   exit(1);
}

Я предполагаю, что этот простой и достаточно короткий, что проверка будет делать лучшую работу, чем модульное тестирование - это, безусловно, будет намного быстрее!

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

положите его другой путь: кодировать государственную машину легок, конструировать правильное одно трудн. Модульные тесты скажут вам только, если вы правильно закодировали дизайн, а не если дизайн был правильным.


тестирование имеет мало общего с шаблонами, шаблонами и т. д. Я бы рекомендовал платформу тестирования, такую как CppUnit (часть семейства xUnit), чтобы захватить все ваши тестовые случаи. Количество будет зависеть от сложности государственной машины, конечно.

ваш вопрос о применении переходов состояния идет в сердце вашего дизайна класса для Вашей государственной машины. Я бы сказал, что у государства будет коллекция дочерних состояний, к которым он может перейти, вместе с событием, которое будет триггера каждого из них. Если событие Foo не имеет ребенка FooBar, то нет способа перейти к нему.

Я бы Google "объектно-ориентированные конечные государственные машины", чтобы начать получать некоторые дизайнерские идеи.

когда я думал о таких проблемах, я думал, что составной шаблон проектирования может быть частью этого, потому что состояние может представлять собой более сложный FSM. У меня был бы интерфейс состояния с SimpleState и CompositeState в качестве реализаций. Мне придется начать все сначала. и посмотрим, все ли получится.


использование государственных машин-это то, что появляется время от времени. Обычно я делаю, как предложил ravenspoint, и просто делаю заявление о переключении. Но это работает только в том случае, если Штаты не слишком велики. Это похоже на твое дело. Принимая это во внимание, я думаю, что лучше всего начать с хорошей архитектуры, которая позволит сделать некоторые вещи, которые вы хотите сделать. Я принял предложение duffymo и попробовал Google. Эта статья выглядела интересной ... --1--Объектно-Ориентированное> Государственные Машины. Это может быть излишним, но я думаю, что это даст структуру, которая будет легко протестировать с чем-то вроде CppUnit.

некоторые другие хорошие ссылки из поиска Google

Конечные Автоматы Основы

Объектно-Ориентированные Конечные Государственные Машины


звучит как нетронутое приложение для модульного тестирования. Существует много систем модульного тестирования. Мне нравится ускорение.


если вы ищете классический шаблон Гоф дизайн модели государственной машины, то посмотрите на Википедия.

взгляните на эту страницу (во время написания) на примере Java.

он имеет StateContext класс, который вы можете видеть из примера использования, имеет клиентов, которые знают о writeName метод. Реализация: this.myState.writeName(this, name); что означает, что он перенаправляет вызов в текущее состояние, передавая себя как первый аргумент.

теперь посмотрим на interface State, Она имеет writeName метод, который соответствует приведенному выше использованию. Если вы посмотрите на обоих StateA и StateB, они возвращаются к контексту, устанавливающему новое состояние.

это большая часть шаблона штата прямо здесь. Единственное, что нужно понять, это то, что StateContext класс может содержать все данные, участвующие в его работе, включая ссылку (она должна быть указателем на C++) на текущее состояние. Все государства коллективно владеют всеми поведение, но нет data, вместо этого откладывая данные (плюс вспомогательные методы) в контексте.

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


Если вам нравится шаблон проектирования состояния, я провел эксперимент и переместил этот шаблон в библиотеку: https://code.google.com/p/dpsmlib/