Je suis dans un projet de système distribué écrit en java où nous avons des classes qui correspondent à des objets métier très complexes. Ces objets ont de nombreuses méthodes correspondant aux actions que l'utilisateur (ou un autre agent) peut appliquer à ces objets. En conséquence, ces classes sont devenues très complexes.
L'approche de l'architecture générale du système a conduit à de nombreux comportements concentrés sur quelques classes et à de nombreux scénarios d'interaction possibles.
À titre d'exemple et pour que les choses soient simples et claires, disons que Robot et Car étaient des classes dans mon projet.
Donc, dans la classe Robot, j'aurais beaucoup de méthodes dans le modèle suivant:
- dormir(); isSleepAvaliable ();
- éveillé(); isAwakeAvaliable ();
- marche (Direction); isWalkAvaliable ();
- tirer (Direction); isShootAvaliable ();
- turnOnAlert (); isTurnOnAlertAvailable ();
- turnOffAlert (); isTurnOffAlertAvailable ();
- recharger(); isRechargeAvailable ();
- éteindre(); isPowerOffAvailable ();
- stepInCar (Voiture); isStepInCarAvailable ();
- stepOutCar (Voiture); isStepOutCarAvailable ();
- auto-destruction(); isSelfDestructAvailable ();
- mourir(); isDieAvailable ();
- est vivant(); est réveillé(); isAlertOn (); getBatteryLevel (); getCurrentRidingCar (); getAmmo ();
- ...
Dans la classe Voiture, ce serait similaire:
- allumer(); isTurnOnAvaliable ();
- éteindre(); isTurnOffAvaliable ();
- marche (Direction); isWalkAvaliable ();
- ravitailler(); isRefuelAvailable ();
- auto-destruction(); isSelfDestructAvailable ();
- crash(); isCrashAvailable ();
- isOperational (); est sur(); getFuelLevel (); getCurrentPassenger ();
- ...
Chacun d'entre eux (Robot et voiture) est implémenté comme une machine à états, où certaines actions sont possibles dans certains états et d'autres non. Les actions modifient l'état de l'objet. Les méthodes d'actions sont lancées IllegalStateException
lorsqu'elles sont appelées dans un état non valide et les isXXXAvailable()
méthodes indiquent si l'action est possible à ce moment-là. Bien que certains soient facilement déductibles de l'état (par exemple, dans l'état de sommeil, l'éveil est disponible), certains ne le sont pas (pour tirer, il doit être éveillé, vivant, avoir des munitions et ne pas conduire de voiture).
De plus, les interactions entre les objets sont également complexes. Par exemple, la voiture ne peut contenir qu'un seul passager robot, donc si un autre essaie d'entrer, une exception doit être levée; Si la voiture s'écrase, le passager doit mourir; Si le robot est mort à l'intérieur d'un véhicule, il ne peut pas sortir, même si la voiture elle-même est ok; Si le robot est à l'intérieur d'une voiture, il ne peut pas en entrer une autre avant de sortir; etc.
Le résultat de cela, comme je l'ai déjà dit, ces classes sont devenues vraiment complexes. Pour aggraver les choses, il existe des centaines de scénarios possibles lorsque le robot et la voiture interagissent. En outre, une grande partie de cette logique doit accéder à des données distantes dans d'autres systèmes. Le résultat est que les tests unitaires sont devenus très difficiles et nous avons beaucoup de problèmes de test, l'un causant l'autre dans un cercle vicieux:
- Les configurations de testcases sont très complexes, car elles doivent créer un monde considérablement complexe à exercer.
- Le nombre de tests est énorme.
- La suite de tests prend quelques heures à s'exécuter.
- Notre couverture de test est très faible.
- Le code de test a tendance à être écrit des semaines ou des mois plus tard que le code qu'ils testent, ou jamais du tout.
- De nombreux tests sont également interrompus, principalement parce que les exigences du code testé ont changé.
- Certains scénarios sont si complexes qu'ils échouent lors de la temporisation lors de la configuration (nous avons configuré une temporisation dans chaque test, dans le pire des cas 2 minutes et même cette fois ils dépassent le délai, nous nous sommes assurés qu'il ne s'agit pas d'une boucle infinie).
- Les bugs se glissent régulièrement dans l'environnement de production.
Ce scénario Robot and Car est une simplification grossière de ce que nous avons en réalité. De toute évidence, cette situation n'est pas gérable. Donc, je demande de l'aide et des suggestions pour: 1, réduire la complexité des classes; 2. Simplifier les scénarios d'interactions entre mes objets; 3. Réduisez la durée du test et la quantité de code à tester.
EDIT:
Je pense que je n'étais pas clair sur les machines d'état. le Robot est lui-même une machine d'état, avec des états "endormi", "éveillé", "en recharge", "mort", etc. La voiture est une autre machine d'état.
EDIT 2: Dans le cas où vous êtes curieux de savoir ce qu'est réellement mon système, les classes qui interagissent sont des choses comme Server, IPAddress, Disk, Backup, User, SoftwareLicense, etc. Le scénario Robot and Car est juste un cas que j'ai trouvé ce serait assez simple pour expliquer mon problème.