我在一开始就道歉,因为这更像是一个设计问题,而不是一个特定的问题所以它可能没有一个简单的答案。无论如何,我正在开发一个非常复杂的代码来处理仓库系统中的事务。事务本身是用户定义的开关,用于确定要在屏幕上输入的字段。我使用命令对象来处理/验证表单。许多验证步骤都很简单,但有些是有点棘手,并且在屏幕字段之间存在交叉依赖关系。例如,我可能会提示用户输入序列引用,但如果这不能唯一地识别纸箱我需要请求一个部分与它一起..我然后点击数据库来验证这些组合..屏幕也可能有一个文件参考供用户输入..这反过来可能与部分/序列交叉引用在屏幕上(通过点击数据库)以确保部件/序列用于文档..这将继续,取决于在事务上定义的内容,具有更多交叉引用和验证。我最终得到的是很多'如果这输入并输入..验证..否则..验证'在命令对象中键入东西,它看起来真的很难看。所以我的问题是:我应该把所有的验证都放在命令对象(所有的数据库检查等)中,还是有更好的地方放置它,有什么我能做的假设这是一个命令对象,那么比我所有复杂的if / else组合更好吗?我曾想过创建当前命令对象可能产生的其他类,使那些可验证并在那些中传播逻辑。如果有人想要芯片我欣赏讨论..
在Joshua的评论之后,我已经开始将代码重构为服务......它还没有完成,但它正在形成..
@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
}
}
}
答案 0 :(得分: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)
}
)
...
}
...
}