Черт возьми, это не так сложно, как кажется. Код конечного автомата очень простой и короткий.
Сохранение состояния в переменной, скажем, 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% прохождении модульных тестов, когда вы не знаете, правильны ли модульные тесты.
Иными словами: кодировать конечный автомат легко, а правильно создать правильный - сложно. Модульные тесты покажут вам, правильно ли вы закодировали проект, а не если проект был правильным.