Ich bin in einem verteilten Systemprojekt, das in Java geschrieben wurde, wo wir einige Klassen haben, die sehr komplexen realen Geschäftsobjekten entsprechen. Diese Objekte verfügen über viele Methoden, die Aktionen entsprechen, die der Benutzer (oder ein anderer Agent) auf diese Objekte anwenden kann. Infolgedessen wurden diese Klassen sehr komplex.
Der allgemeine Architekturansatz des Systems hat zu vielen Verhaltensweisen geführt, die sich auf wenige Klassen und viele mögliche Interaktionsszenarien konzentrieren.
Nehmen wir als Beispiel und um die Dinge einfach und klar zu halten, sagen wir, dass Roboter und Auto Klassen in meinem Projekt waren.
In der Roboterklasse hätte ich also viele Methoden im folgenden Muster:
- Schlaf(); isSleepAvaliable ();
- Erwachen(); isAwakeAvaliable ();
- gehen (Richtung); isWalkAvaliable ();
- schießen (Richtung); isShootAvaliable ();
- turnOnAlert (); isTurnOnAlertAvailable ();
- turnOffAlert (); isTurnOffAlertAvailable ();
- aufladen(); isRechargeAvailable ();
- ausschalten(); isPowerOffAvailable ();
- stepInCar (Auto); isStepInCarAvailable ();
- stepOutCar (Auto); isStepOutCarAvailable ();
- Selbstzerstörung(); isSelfDestructAvailable ();
- sterben(); isDieAvailable ();
- ist am Leben(); ist wach(); isAlertOn (); getBatteryLevel (); getCurrentRidingCar (); getAmmo ();
- ...
In der Autoklasse wäre es ähnlich:
- anschalten(); isTurnOnAvaliable ();
- abschalten(); isTurnOffAvaliable ();
- gehen (Richtung); isWalkAvaliable ();
- tanken(); isRefuelAvailable ();
- Selbstzerstörung(); isSelfDestructAvailable ();
- Absturz(); isCrashAvailable ();
- isOperational (); isOn (); getFuelLevel (); getCurrentPassenger ();
- ...
Jedes dieser Elemente (Roboter und Auto) ist als Zustandsmaschine implementiert, wobei einige Aktionen in einigen Zuständen möglich sind und andere nicht. Die Aktionen ändern den Status des Objekts. Die Aktionsmethoden werden ausgelöst, IllegalStateException
wenn sie in einem ungültigen Zustand aufgerufen werden, und die isXXXAvailable()
Methoden geben an, ob die Aktion zu diesem Zeitpunkt möglich ist. Obwohl einige leicht aus dem Zustand abgeleitet werden können (z. B. im Schlafzustand ist Wach verfügbar), sind andere nicht (um zu schießen, muss es wach, lebendig, mit Munition sein und kein Auto fahren).
Darüber hinaus sind auch die Wechselwirkungen zwischen den Objekten komplex. ZB kann das Auto nur einen Roboterpassagier halten. Wenn also ein anderer versucht einzutreten, sollte eine Ausnahme ausgelöst werden. Wenn das Auto abstürzt, sollte der Passagier sterben; Wenn der Roboter in einem Fahrzeug tot ist, kann er nicht aussteigen, auch wenn das Auto selbst in Ordnung ist. Befindet sich der Roboter in einem Auto, kann er vor dem Aussteigen keinen anderen betreten. etc.
Das Ergebnis ist, wie ich bereits sagte, dass diese Klassen wirklich komplex wurden. Um die Sache noch schlimmer zu machen, gibt es Hunderte von möglichen Szenarien, in denen der Roboter und das Auto interagieren. Darüber hinaus muss ein Großteil dieser Logik auf entfernte Daten in anderen Systemen zugreifen. Das Ergebnis ist, dass Unit-Tests sehr schwierig wurden und wir viele Testprobleme haben, von denen eines das andere in einem Teufelskreis verursacht:
- Die Testfall-Setups sind sehr komplex, da sie eine sehr komplexe Welt zum Trainieren erstellen müssen.
- Die Anzahl der Tests ist enorm.
- Die Ausführung der Testsuite dauert einige Stunden.
- Unsere Testabdeckung ist sehr gering.
- Der Testcode wird in der Regel Wochen oder Monate später als der von ihnen getestete Code oder überhaupt nicht geschrieben.
- Viele Tests sind ebenfalls fehlerhaft, hauptsächlich weil sich die Anforderungen des getesteten Codes geändert haben.
- Einige Szenarien sind so komplex, dass sie beim Setup während des Setups fehlschlagen (wir haben in jedem Test ein Timeout konfiguriert, im schlimmsten Fall 2 Minuten lang und selbst dieses Mal haben wir sichergestellt, dass es sich nicht um eine Endlosschleife handelt).
- Fehler treten regelmäßig in der Produktionsumgebung auf.
Dieses Roboter- und Autoszenario ist eine grobe Vereinfachung dessen, was wir in der Realität haben. Diese Situation ist eindeutig nicht beherrschbar. Deshalb bitte ich um Hilfe und Vorschläge, um: 1, die Komplexität der Klassen zu reduzieren; 2. Vereinfachen Sie die Interaktionsszenarien zwischen meinen Objekten. 3. Reduzieren Sie die Testzeit und die Menge des zu testenden Codes.
EDIT:
Ich glaube, ich war nicht klar über die Zustandsmaschinen. Der Roboter selbst ist eine Zustandsmaschine mit den Zuständen "schlafen", "wach", "aufladen", "tot" usw. Das Auto ist eine andere Zustandsmaschine.
EDIT 2: Für den Fall, dass Sie neugierig sind, was mein System tatsächlich ist, sind die Klassen, die interagieren, Dinge wie Server, IPAddress, Disk, Backup, Benutzer, SoftwareLicense usw. Das Szenario Roboter und Auto ist nur ein Fall, den ich gefunden habe das wäre einfach genug, um mein Problem zu erklären.