2014-08-27 67 views
0

我从一开始就表示歉意,因为这是更多的设计问题,而不是一个特定的问题,所以它可能没有一个简单的答案。无论如何,我正在开发一个相当复杂的一段代码来处理事务在仓库系统中。交易本身是由用户定义的开关,用于确定在屏幕上输入的字段。我使用命令对象来处理/验证表单。许多验证步骤都很简单,但有些技巧有点棘手,并且在屏幕字段之间存在交叉依赖关系。因此,例如,我可能会提示用户输入序列参考,但如果没有唯一标识我需要的纸箱请求一个部分去与它..然后我点击数据库验证这些组合..屏幕也可能有一个文件引用供用户输入..这反过来可能交叉引用的部分/序列上的屏幕(通过点击数据库)以确保零件/序列是用于文件的。这取决于交易中定义的内容,并继续交叉引用和验证。我最终得到的是很多'如果这个进入,这进入..验证..否则..验证'类型的东西在命令对象,它看起来非常丑陋..所以我的问题是:我应该把所有我的验证在命令对象(所有的数据库检查等)或有更好的地方,有什么我可以做比我所有复杂的if/else组合,因为这是一个命令对象吗?我曾想过创建当前命令对象可能产生的其他类,使这些可验证的并将逻辑分散到那些之中。如果有人想要芯片,我会欣赏讨论。Grails commandObject - 设计最佳实践

约书亚的评论我已经开始了代码重构到服务..这不是完整的,但它的雏形..

@Transactional 
class TransactionValidationService { 

static enum state { 
    RECEIPT, 
    RECEIPT_SERIAL, 
    RECEIPT_DOCUMENT, 
    RECEIPT_PART, 
    RECEIPT_SERIAL_PART, 
    RECEIPT_SERIAL_DOCUMENT, 
    RECEIPT_PART_DOCUMENT, 
    ISSUE, 
    TRANSFER 
} 

def validateTransaction(TransactionDetailCommand transaction) { 

    // Set initial state .. 

    def currentState 

    switch (transaction.transactionType.processType) { 

     case ProcessType.ISSUE: 
      currentState = state.ISSUE 
      break 

     case ProcessType.RECEIPT: 
      currentState = state.RECEIPT 
      break 

     case ProcessType.TRANSFER: 
      currentState = state.TRANSFER 

    } 

    switch (currentState) { 

     case state.RECEIPT: 

      if (transaction.serialReference) { 
       // validateSerialReference 
       currentState = state.RECEIPT_SERIAL 
      } else if (transaction.documentHeader) { 
       // validateReceiptDocument 
       currentState = state.RECEIPT_DOCUMENT 
      } 

      break 

     case state.RECEIPT_SERIAL: 

      if (transaction.part) { 
       // validatePartSerial 
       currentState = state.RECEIPT_SERIAL_PART 
      } 

      if (transaction.documentHeader) { 
       // validateDocumentPart 
       currentState = state.RECEIPT_SERIAL_DOCUMENT 
      } 

      break 

     case state.ISSUE: 
      break 

     case state.TRANSFER: 
      break 

    } 

} 

}

回答

1

首先,用命令对象来收集这些信息是正确的选择。

但是,在自定义验证器的约束条件下实现复杂的验证逻辑可能有点压倒一切。您可能需要考虑将注册服务注入您的命令对象,然后将验证委托给自定义验证程序中的服务。

例如

@Validateable 
@ToString(includeNames=true) 
class MyExampleCommand { 
    def myValidationService = Holders.grailsApplication.mainContext.myValidationService 

    String someThing 
    Long someValue 
    .. 
    static constraints = { 
    someThing(
     nullable: false, 
     blank: false, 
     size:1..20, 
     validator: { val, obj -> 
     obj.myValidationService.validateSomeThing(obj) 
     } 
    ) 
    ... 
    } 
    ... 
} 
+0

感谢您的..我会看看它能走多远需要我 - 尤其是我所有的丑陋如果else结构.. – user3914455 2014-08-27 17:25:44

+0

你可能要考虑重构变成一只FSM(有限状态机)。 – 2014-08-27 17:40:14

+0

你会考虑看一些小代码,让我知道我是否在正确的路线上? – user3914455 2014-08-28 10:50:00