我知道标题有点过于宽泛,但我想知道如何避免(如果可能)我刚刚在我们的解决方案上编写的这段代码。
当此代码导致日志信息不足时,问题就开始了:
...
var users = [someRemotingProxy].GetUsers([someCriteria]);
try
{
var user = users.Single();
}
catch (InvalidOperationException)
{
logger.WarnFormat("Either there are no users corresponding to the search or there are multiple users matching the same criteria.");
return;
}
...
我们的模块中有一个业务逻辑,需要有一个匹配某些标准的“用户”。事实证明,当问题开始出现时,这个小小的“不确定”信息不足以让我们正确知道发生了什么,所以我编写了这个方法:
private User GetMappedUser([searchCriteria])
{
var users = [remotingProxy]
.GetUsers([searchCriteria])
.ToList();
switch (users.Count())
{
case 0:
log.Warn("No user exists with [searchCriteria]");
return null;
case 1:
return users.Single();
default:
log.WarnFormat("{0} users [{1}] have been found"
users.Count(),
String.Join(", ", users);
return null;
}
然后像这样从主代码中调用它:
...
var user = GetMappedUser([searchCriteria]);
if (user == null) return;
...
我看到的第一件奇怪的事情是清单上的switch
声明。.Count()
起初这似乎很奇怪,但不知何故最终成为更清洁的解决方案。我在这里尝试避免异常,因为这些情况很正常,而且我听说尝试使用异常来控制程序流程而不是报告实际错误是不好的。代码之前是从 Single 抛出的InvalidOperationException
,所以这更像是一个重构。
对于这个看似简单的问题,还有另一种方法吗?这似乎是一种违反单一责任原则的行为,日志介于代码和所有内容之间,但我看不到一个体面或优雅的方法。在我们的例子中情况更糟,因为相同的步骤重复了两次,一次是针对“用户”,然后是针对“设备”,如下所示:
- 获取唯一用户
- 获取唯一用户的唯一设备
对于这两种操作,重要的是我们要确切地知道发生了什么,如果它不是唯一的,则返回了哪些用户/设备,诸如此类。