在这个时刻,我正面临着我的设计中的一个主要问题。我的方法试图完成以下操作:用依赖关系在scala代码中调用外部服务
- 将传入的对象插入到数据库中。
- 从插入中获取自动增加的ID并使用它与对象一起调用webservice1。
- 从webservice1获取结果,并使用原始对象和webservice1的一些响应调用webservice2。
- 结合webservice1和2的结果并将其写入数据库。
- 从最后一次插入中获取生成的自动增量标识,并调用webservice3与最终导致操作成功或失败的原始对象。
我想以灵活的方式进行设计,因为需求是不断变化的,我不想在任何变化的基础上继续修改我的逻辑。我意识到一些变化是不可避免的,但我想尽量减少损害并尊重开放封闭原则。
我最初采取如下:
def complexOperation(someObject:T) =
dbService.insertIntoDb(someObject) match {
case Left(e:Exception) => Left(e)
case Right(id:Int) => webService.callWebService1(id,someObject) match {
case Left(e:Exception) => Left(e)
case Right(r:SomeResponse1) => webService.callWebservice2(r,someObject) match {
case Left(e:Exception) => webService.rollbackService1();Left(e)
case Right(context:ResponseContext) => dbService.insertContextIntoDb(context) match {
case Left(e:Exception) => Left(e)
case Right(id:Int) => webService.callWebservice3(id,someObject) match {
case Left(e:Exception) => webService.rollbackService3();Left(e)
case Right(r:Response) => Right(r)
}
}
}
}
正如你所看到的,这是一团乱麻。我不能单元测试它,也不能扩展它,也不能很容易地调试它,如果事情失控了。这段代码可以达到它的目的,但是如果能够对如何重构它,让继承我的代码的人们的生活变得更容易一些,我会很高兴。
谢谢
谢谢迪伦。这是非常有趣的东西。不幸的是,我陷入了需要重构的2.9.1代码库。有没有一种惯用的scala方式来平面映射到Either上,这会反过来在任何发生异常的发生器上透明地冒泡Exceptions,而不会继续进行其余的计算?另外,“recoverWith”是Try [T]属性吗? –
最后一个问题第一:'recoverWith'确实是'Try [T]'方法。我在答案中链接的文档解释得非常好。至于你的第一个问题,我不知道任何现有的解决方案,直接运行'Either' – Dylan
@sc_ray我看了一下,并编辑了我的答案。希望这会对你有用。 – Dylan