从函数返回数据的最佳实践是什么?是返回Null对象好还是返回空对象好?为什么要选择一种而不是另一种呢?
考虑一下:
public UserEntity GetUserById(Guid userId)
{
//Imagine some code here to access database.....
//Check if data was returned and return a null if none found
if (!DataExists)
return null;
//Should I be doing this here instead?
//return new UserEntity();
else
return existingUserEntity;
}
让我们假设在这个程序中存在有效的情况,即数据库中没有具有该GUID的用户信息。我认为在这种情况下抛出异常是不合适的??另外,我的印象是异常处理会损害性能。
还有一种方法涉及传入一个回调对象或委托,它将对值进行操作。如果没有找到值,则不调用回调。
public void GetUserById(Guid id, UserCallback callback)
{
// Lookup user
if (userFound)
callback(userEntity); // or callback.Call(userEntity);
}
当您希望避免在整个代码中进行空检查时,以及当找不到值并不是错误时,这种方法非常有效。如果需要任何特殊处理,还可以在没有找到对象时提供回调。
public void GetUserById(Guid id, UserCallback callback, NotFoundCallback notFound)
{
// Lookup user
if (userFound)
callback(userEntity); // or callback.Call(userEntity);
else
notFound(); // or notFound.Call();
}
使用单个对象的相同方法如下所示:
public void GetUserById(Guid id, UserCallback callback)
{
// Lookup user
if (userFound)
callback.Found(userEntity);
else
callback.NotFound();
}
从设计的角度来看,我真的很喜欢这种方法,但是它的缺点是在不支持第一类函数的语言中使调用站点变得更庞大。
这取决于什么对你的案子最有意义。
返回null是否有意义?“不存在这样的用户”?
或者创建一个默认用户有意义吗?当您可以安全地假设如果用户不存在,则调用代码在请求时希望用户存在时,这是最有意义的。
或者,如果调用代码要求使用无效ID的用户,抛出异常(如“FileNotFound”)是否有意义?
然而,从分离关注点/SRP的角度来看,前两点更为正确。从技术上讲,第一个是最正确的(但只差一点点)——GetUserById应该只负责一件事——获取用户。通过返回其他内容来处理自己的“用户不存在”情况可能违反SRP。如果您确实选择抛出异常,则分隔为不同的check - bool DoesUserExist(id)是合适的。
根据下面大量的评论:如果这是一个api级别的设计问题,这个方法可以类似于“OpenFile”或“readwholfile”。我们正在从某个存储库中“打开”一个用户,并从结果数据中补充对象。在这种情况下,一个例外可能是合适的。也许不是,但也有可能。
所有的方法都是可以接受的——这取决于API/应用程序的上下文。