我在用Java编写的分布式系统项目中,其中有一些类对应于非常复杂的现实世界业务对象。这些对象具有许多与用户(或某些其他代理)可以应用于该对象的操作相对应的方法。结果,这些类变得非常复杂。
系统通用体系结构方法导致许多行为集中在少数几个类上,并且涉及许多可能的交互方案。
举个例子,为了使事情变得简单明了,假设机器人和汽车是我项目中的类。
因此,在Robot类中,我将采用以下模式提供许多方法:
- 睡觉(); isSleepAvaliable();
- 苏醒(); isAwakeAvaliable();
- 步行(方向);isWalkAvaliable();
- 射击(方向);isShootAvaliable();
- turnOnAlert(); isTurnOnAlertAvailable();
- turnOffAlert(); isTurnOffAlertAvailable();
- recharge(); isRechargeAvailable();
- powerOff(); isPowerOffAvailable();
- stepInCar(Car); isStepInCarAvailable();
- stepOutCar(Car); isStepOutCarAvailable();
- 自毁(); isSelfDestructAvailable();
- 死(); isDieAvailable();
- 活着(); isAwake(); isAlertOn(); getBatteryLevel(); getCurrentRidingCar(); getAmmo();
- ...
在Car类中,它将类似于:
- 打开(); isTurnOnAvaliable();
- 关掉(); isTurnOffAvaliable();
- 步行(方向);isWalkAvaliable();
- 加油(); isRefuelAvailable();
- 自毁(); isSelfDestructAvailable();
- crash(); isCrashAvailable();
- isOperational(); isOn(); getFuelLevel(); getCurrentPassenger();
- ...
这些(机器人和汽车)中的每一个都实现为状态机,在某些状态下某些动作是可能的,而在某些状态下则不可能。这些动作将更改对象的状态。IllegalStateException
当在无效状态下调用时,actions方法将引发,并且这些isXXXAvailable()
方法将告知当时是否可以执行该操作。尽管可以从状态轻松推断出某些状态(例如,在睡眠状态下可以清醒),但是某些状态则不行(要开枪,它必须醒着,还活着,有弹药并且不开车)。
此外,对象之间的交互也很复杂。例如,汽车只能容纳一名机器人乘客,因此如果另一名乘客试图进入,则应抛出异常;如果汽车撞车,乘客应该死亡;如果机器人死于车内,即使汽车本身没问题,他也无法走出。如果机器人在汽车内,则他不能在下车之前进入另一个机器人。等等
正如我已经说过的那样,这些类变得非常复杂。更糟糕的是,机器人与汽车互动时有数百种可能的情况。此外,许多逻辑确实需要访问其他系统中的远程数据。结果是,单元测试变得非常困难,并且我们遇到了很多测试问题,一个导致另一个问题处于恶性循环:
- 测试用例的设置非常复杂,因为它们需要创建一个非常复杂的世界来执行。
- 测试数量巨大。
- 测试套件需要几个小时才能运行。
- 我们的测试覆盖率很低。
- 测试代码往往比其测试的代码晚几周或几个月编写,或者根本不会编写。
- 许多测试也被破坏了,主要是因为被测试代码的需求已更改。
- 某些情况是如此复杂,以至于在设置期间会超时(我们在每个测试中都配置了超时,在最坏的情况下,超时时间为2分钟,即使这段时间超时,我们也确保它不是无限循环)。
- 错误通常会潜入生产环境。
机器人和汽车的场景是对我们现实中的事物的过度简化。显然,这种情况是无法控制的。因此,我在寻求帮助和建议:1,降低类的复杂性;2.简化对象之间的交互方案;3.减少测试时间和要测试的代码量。
编辑:
我想我还不清楚状态机。机器人本身就是状态机,状态为“睡眠”,“清醒”,“正在充电”,“死亡”等。汽车是另一种状态机。
编辑2:如果您对我的系统实际是一个很好的情况感到好奇,则交互的类是诸如Server,IPAddress,Disk,Backup,User,SoftwareLicense等之类的东西。Robot和Car场景只是我发现的一个案例那将足以解释我的问题。