Я нахожусь в проекте распределенной системы, написанном на Java, где у нас есть несколько классов, которые соответствуют очень сложным объектам реального мира. Эти объекты имеют множество методов, соответствующих действиям, которые пользователь (или некоторый другой агент) может применить к этим объектам. В результате эти занятия стали очень сложными.
Системный подход к общей архитектуре привел к тому, что многие виды поведения были сконцентрированы на нескольких классах и множестве возможных сценариев взаимодействия.
В качестве примера и для простоты и ясности, скажем, что Robot и Car были классами в моем проекте.
Итак, в классе Robot у меня было бы много методов по следующей схеме:
- спать(); isSleepAvaliable ();
- бодрствования (); isAwakeAvaliable ();
- ходить (направление); isWalkAvaliable ();
- стрелять (направление); isShootAvaliable ();
- turnOnAlert (); isTurnOnAlertAvailable ();
- turnOffAlert (); isTurnOffAlertAvailable ();
- перезарядки (); isRechargeAvailable ();
- выключить(); isPowerOffAvailable ();
- stepInCar (Car); isStepInCarAvailable ();
- stepOutCar (Car); isStepOutCarAvailable ();
- саморазрушение(); isSelfDestructAvailable ();
- умереть(); isDieAvailable ();
- является живым(); isAwake (); isAlertOn (); getBatteryLevel (); getCurrentRidingCar (); getAmmo ();
- ...
В классе автомобилей это было бы похоже:
- включить(); isTurnOnAvaliable ();
- выключи(); isTurnOffAvaliable ();
- ходить (направление); isWalkAvaliable ();
- заправлять (); isRefuelAvailable ();
- саморазрушение(); isSelfDestructAvailable ();
- аварии (); isCrashAvailable ();
- isOperational (); Ison (); getFuelLevel (); getCurrentPassenger ();
- ...
Каждый из них (Робот и Автомобиль) реализован как конечный автомат, где некоторые действия возможны в некоторых состояниях, а некоторые нет. Действия изменяют состояние объекта. Методы действия выдают, IllegalStateException
когда вызываются в недопустимом состоянии, и isXXXAvailable()
методы сообщают, возможно ли действие в данный момент. Хотя некоторые из них легко выводятся из состояния (например, в состоянии сна, бодрствование доступно), некоторые - нет (чтобы стрелять, он должен быть бодрствующим, живым, иметь боеприпасы и не ездить на машине).
Кроме того, взаимодействия между объектами тоже сложны. Например, автомобиль может содержать только одного пассажира робота, поэтому, если другой попытается въехать, должно быть выдано исключение; Если машина падает, пассажир должен умереть; Если робот мертв в транспортном средстве, он не может выйти, даже если с самим автомобилем все в порядке; Если робот находится внутри автомобиля, он не может войти в другой, прежде чем выйти; и т.п.
В результате, как я уже сказал, эти занятия стали действительно сложными. Что еще хуже, есть сотни возможных сценариев, когда робот и автомобиль взаимодействуют. Кроме того, большая часть этой логики требует доступа к удаленным данным в других системах. В результате юнит-тестирование стало очень трудным, и у нас много проблем с тестированием, одно из которых приводит к порочному кругу:
- Установки тестовых сценариев очень сложны, потому что они должны создать значительно более сложный мир для тренировок.
- Количество тестов огромно.
- Тестовый набор занимает несколько часов.
- Наш тестовый охват очень низкий.
- Код тестирования, как правило, пишется на несколько недель или месяцев позже, чем код, который они тестируют, или никогда.
- Многие тесты тоже не пройдены, в основном из-за того, что требования тестируемого кода изменились.
- Некоторые сценарии настолько сложны, что во время установки они терпят неудачу по таймауту (мы настраивали тайм-аут в каждом тесте, в худшем случае - 2 минуты, и даже если этот тайм-аут был продолжительным, мы убедились, что это не бесконечный цикл).
- Ошибки регулярно проскальзывают в производственную среду.
Этот сценарий «Робот и машина» является чрезмерным упрощением того, что мы имеем на самом деле. Очевидно, что эта ситуация не управляема. Итак, я прошу помощи и предложений: 1, уменьшить сложность занятий; 2. Упростить сценарии взаимодействия между моими объектами; 3. Уменьшите время тестирования и количество кода, который будет проверен.
РЕДАКТИРОВАТЬ:
Я думаю, что я не был ясен о государственных машинах. Робот сам по себе является конечным автоматом с состояниями «спящий», «бодрствующий», «перезарядка», «мертвый» и т. д. Автомобиль - это еще один конечный автомат.
РЕДАКТИРОВАТЬ 2: В случае, если вам интересно, что на самом деле представляет собой моя система, взаимодействующие классы - это такие вещи, как Сервер, IP-адрес, Диск, Резервное копирование, Пользователь, SoftwareLicense и т. Д. Сценарий «Робот и машина» - это как раз тот случай, который я обнаружил. это было бы достаточно просто, чтобы объяснить мою проблему.