Разработка конечного автомата в C++

У меня есть немного проблемы, которая включает моделирование конечного автомата.

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

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

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

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

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

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

7
задан SCFrench 14 October 2010 в 13:24
поделиться

6 ответов

Обязательно ознакомьтесь с библиотекой Boost Statechart Library .

7
ответ дан 6 December 2019 в 21:11
поделиться

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

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

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

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

1
ответ дан 6 December 2019 в 21:11
поделиться

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

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

Структура конечного автомата

Объектно-ориентированные конечные автоматы

1
ответ дан 6 December 2019 в 21:11
поделиться

Если вы ищете классический шаблон конечного автомата шаблонов проектирования GOF, посмотрите википедию .

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

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

Теперь посмотрите на Состояние интерфейса , у него есть метод writeName , который соответствует описанному выше использованию. Если вы посмотрите и на StateA , и на StateB , они обратятся к контексту, устанавливающему новое состояние.

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

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

0
ответ дан 6 December 2019 в 21:11
поделиться

Черт возьми, это не так сложно, как кажется. Код конечного автомата очень простой и короткий.

Сохраните состояние в переменной, скажем 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% модульного теста, если вы плохо понимаете, правильны ли модульные тесты.

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

3
ответ дан 6 December 2019 в 21:11
поделиться

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

0
ответ дан 6 December 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: