从函数返回数据的最佳实践是什么?是返回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的用户信息。我认为在这种情况下抛出异常是不合适的??另外,我的印象是异常处理会损害性能。


当前回答

我会说返回null而不是空对象。

但你在这里提到的具体例子, 您正在通过用户id搜索用户,即排序 那个用户的键,在这种情况下,我可能想要 如果没有用户实例,则抛出异常 发现。

这是我通常遵循的规则:

如果通过主键查找操作没有找到结果, 把ObjectNotFoundException。 如按任何其他标准没有发现结果, 返回null。 如果通过非关键条件查找未找到结果,则可能返回多个对象 返回一个空集合。

其他回答

我对答案的数量感到困惑(在整个网络上),说你需要两个方法:“IsItThere()”方法和“GetItForMe()”方法,所以这导致了一个竞争条件。一个函数返回null,将它分配给一个变量,并在一次测试中检查变量是否为null,这有什么问题?我以前的C代码中充斥着

if (NULL !=(变量=函数(参数…))){

因此,您可以同时获得变量中的值(或null)和结果。这个成语已经被遗忘了吗?为什么?

请原谅我的伪php/代码。

我认为这真的取决于结果的预期用途。

如果你想编辑/修改返回值并保存它,那么返回一个空对象。这样,您就可以使用相同的函数在新对象或现有对象上填充数据。

假设我有一个函数,它接受一个主键和一个数据数组,用数据填充行,然后将结果记录保存到db。因为我打算用我的数据填充对象,所以从getter返回一个空对象可能是一个巨大的优势。这样,我可以在两种情况下执行相同的操作。无论如何都要使用getter函数的结果。

例子:

function saveTheRow($prim_key, $data) {
    $row = getRowByPrimKey($prim_key);

    // Populate the data here

    $row->save();
}

在这里,我们可以看到相同的一系列操作操作了该类型的所有记录。

但是,如果返回值的最终目的是读取数据并对数据做一些事情,那么我将返回null。这样,我可以非常快速地确定是否没有返回数据,并向用户显示适当的消息。

通常,我将在检索数据的函数中捕获异常(因此我可以记录错误消息等),然后从捕获中直接返回null。对于最终用户来说,问题是什么通常并不重要,因此我发现最好将错误记录/处理直接封装在获取数据的函数中。如果你在任何大公司维护一个共享的代码库,这是特别有益的,因为你可以强制适当的错误记录/处理,即使是最懒的程序员。

例子:

function displayData($row_id) {
    // Logging of the error would happen in this function
    $row = getRow($row_id);
    if($row === null) {
        // Handle the error here
    }

    // Do stuff here with data
}

function getRow($row_id) {
 $row = null;
 try{
     if(!$db->connected()) {
   throw excpetion("Couldn't Connect");
  }

  $result = $db->query($some_query_using_row_id);

  if(count($result) == 0 ) {
   throw new exception("Couldn't find a record!");
  }

  $row = $db->nextRow();

 } catch (db_exception) {
  //Log db conn error, alert admin, etc...
  return null; // This way I know that null means an error occurred
 }
 return $row;
}

这是我的一般原则。到目前为止,它运行得很好。

如果返回类型是数组,则返回空数组,否则返回null。

如果您打算表示没有可用的数据,返回null通常是最好的主意。

空对象表示已返回数据,而返回null则明确表示没有返回任何数据。

此外,如果试图访问对象中的成员,返回null将导致null异常,这对于突出显示有bug的代码很有用——试图访问没有任何成员的成员是没有意义的。访问空对象的成员不会失败,这意味着bug不会被发现。

这是一个业务问题,取决于具有特定Guid Id的用户的存在是否是该函数的预期正常用例,还是会阻止应用程序成功完成该方法向用户对象提供的任何功能的异常情况……

如果它是一个“异常”,因为缺少具有该Id的用户将阻止应用程序成功完成它正在做的任何功能,(假设我们正在为我们已向其发货的客户创建发票……),那么这种情况应该抛出ArgumentException(或其他一些自定义异常)。

如果没有用户(调用此函数的潜在正常结果之一),则返回空值....

编辑:(处理亚当在另一个回答中的评论)

If the application contains multiple business processes, one or more of which require a User in order to complete successfully, and one or more of which can complete successfully without a user, then the exception should be thrown further up the call stack, closer to where the business processes which require a User are calling this thread of execution. Methods between this method and that point (where the exception is being thrown) should just communicate that no user exists (null, boolean, whatever - this is an implementation detail).

但是如果应用程序中的所有进程都需要一个用户,我仍然会在这个方法中抛出异常……