我在C#中使用代码契约,但我有点好奇我应该为userMessage
参数输入什么。我将举一个简短的例子。
我的代码中有以下断言:
Contract.Assert(IsValidReferenceData(refData));
此消息永远不会显示给用户,但是对于我自己和该软件的其他开发人员/维护人员来说,在例外中添加英文消息说明会很好。
最初我想过
Contract.Assert(IsValidReferenceData(refData), "Payment Reference is not valid");
但后来我认为userMessage
与布尔条件完全相反,所以我把它重写为:
Contract.Assert(IsValidReferenceData(refData), "Payment Reference is valid");
因此消息和条件是相同的。然而,这会让人们在看到异常报告时会感到困惑,然后再想一想,如果引用有效,那么为什么会抛出异常?"。
最后,我想,为什么不做一个中立的陈述,其中 必须是真的:
Contract.Assert(IsValidReferenceData(refData), "Payment Reference must be valid");
以上哪项是最佳做法?我希望得到正确的消息,因为我计划在整个地方使用断言,以防止数据的不规则,为此我启用了运行时检查。
答案 0 :(得分:4)
所以,有了.Net代码,我决定查看它们用作参数的内容,结果如下:
"hashcode >= 0"
"Race condition detected in usages of Hashtable - multiple threads appear to be writing to a Hashtable instance simultaneously! Don't do that - use Hashtable.Synchronized."
"Invalid MaxPrimeArrayLength"
"Missing case in GetRandomizedEqualityComparer!"
"We increment our current index by 8, so our buffer size must be a multiple of 8"
"key shouldn't be null!"
"Size is not zero"
"Didn't set Console::_out or _error appropriately!"
"Setting the foreground color before we've read the default foreground color!"
此处更多:http://pastebin.com/zPgU1ALe
基本上答案是:写下您想要的任何内容,此消息旨在让您快速调试,而不是为您的api用户编写。
答案 1 :(得分:3)
代码契约(断言,前置和后置条件以及不变量)用于检测代码未设计用于处理的带外操作条件。它们不应该用作验证的第一点,因此Contracts
不应该关注上下文用户消息。表示/服务层中的上游验证应该已经识别出任何无效的用户或服务客户端输入。
鉴于该消息仅在合同失败时显示,理论上在生产代码中永远不会出现,这意味着此处的目标“用户”受众将是您或其他开发人员,因此,应该定制消息以帮助您快速调试它(如果您需要一条消息 - 堆栈跟踪和行号通常就足够了,IMO)。我想参数名userMessage
可能是一个不幸的选择。
答案 2 :(得分:2)
值得一提的是,虽然没有针对失败代码合同的用户消息指南,但有一个xUnit test pattern名为期望描述消息,适合您的上一个示例。通过回答关于断言消息中应该发生了什么的问题,您实现了两个目标:代码可读性+提供有用的,不言自明的调试消息。