有状态与无状态服务Grails

有状态与无状态服务Grails,grails,service,groovy,Grails,Service,Groovy,当我掉进grails服务的兔子洞时,我目前正在将业务逻辑从控制器方法移动到服务。我的服务中有以下方法: Job closeJobOpportunity(Job op, Employee res) { op.chosenOne = res op.requisitionCanceledDate = new Date() if(!op.chosenOne || !op.hrEffectiveDate){ return null } else i

当我掉进grails服务的兔子洞时,我目前正在将业务逻辑从控制器方法移动到服务。我的服务中有以下方法:

Job closeJobOpportunity(Job op, Employee res) {
    op.chosenOne = res
    op.requisitionCanceledDate = new Date() 
    if(!op.chosenOne || !op.hrEffectiveDate){
        return null
    }
    else if(StringUtils.isEmpty(op.chosenOne.id)){
        return null
    }
    return op
}
我开始考虑这种方法可能导致同步问题的不同方式(因为grails使服务成为单例),并注意到grails文档提到只要不存储状态,业务逻辑就应该放在服务中


冒着听起来无知或信息不灵通的风险,有人能简单地在Grails中提供有状态和无状态服务之间的区别吗?上述方法是否有状态?然后它是否应该被控制器中的try-catch包围

Grails服务(或类的任何其他实例)中有状态和无状态的区别取决于实例本身是否持有任何状态

首先,很难说您的示例中的服务是否是无状态的,但是您在该特定方法中的交互并不表示您正在对服务本身执行任何有状态的操作。这会让我相信服务将是无状态的

让我给你一个有状态服务的例子,并解释为什么它是有状态的

class MyStatefulService {
  Long someNumber
  String someString

  void doSomething(Long addMe) {
    someNumber += addMe
  }

  void updateSomething(String newValue) {
    someString = newValue
  }
}
正如您所看到的,上面的服务有两个属性。如果此服务创建为单实例,那么对它的所有调用都将使用同一个实例。正如您所看到的,服务上的两个方法会影响服务的属性或状态。这意味着,在它的当前形式中,您不能确保在特定线程执行服务的一个或多个方法时状态没有改变。使它不可靠,以目前的形式。虽然这是一个非常简单的示例,但它确实演示了如何使服务有状态

服务有属性是可以的,而且通常是这样。它们可以是对其他服务的引用,甚至可以是配置值。关键的概念是确保它们不会改变状态(总是有例外,但它们是边缘情况)

完全可以将服务重写为有状态、同步等,以避免多线程访问和修改状态的陷阱,但这不是您应该做的事情。无状态服务更简单、更干净、更易于测试、更易于调试和更轻量级


简言之,让您的服务成为无状态的,省去您自己的麻烦。

我同意上面的回答,其中特别详细介绍了有状态服务和无状态服务。我还同意将业务逻辑移出控制器层并避免“胖控制器”反模式的过程。然而,要回答一个稍微不同的问题,可能是隐含的问题,我不需要跳到服务层中填充所有内容

这取决于你的应用程序的复杂性。从短期来看,服务层的业务逻辑很吸引人,但我觉得从长期来看,它会导致程序性思维和难以扩展或重用的代码。如果你想知道实际的业务逻辑应该放在哪里,我建议你花30分钟看这个演讲