Return early, return often

I'm fixing some code we wrote for the Mouse Lock implementation, based on review comments.  I had forgotten how many of my colleagues teach our students that you should avoid multiple exit points from a function.  It meant that our implementation code had a bunch of deep nesting in order to avoid early returns.  We need to stop teaching that.  There's nothing wrong with "bailing early."

Here's the code in question:

    // When exiting fullscreen, if the pointer is also locked to the fullscreen element,  
    // we'll need to unlock it as we the document exits fullscreen.  
    nsCOMPtr window = aDocument->GetWindow();  
    if (window) {  
        nsCOMPtr navigator;  
        window->GetNavigator(getter_AddRefs(navigator));  
        if (navigator) {  
            nsCOMPtr navigatorPointerLock = do_QueryInterface(navigator);  
            if (navigatorPointerLock) {  
                nsCOMPtr pointer;  
                navigatorPointerLock->GetMozPointer(getter_AddRefs(pointer));  
                if (pointer) {  
                    // Unlock will bail early if not really locked  
                    pointer->Unlock();  
                }  
            }  
        }  
    }

Here's how it should look:

  // When exiting fullscreen, if the pointer is also locked to the fullscreen element,  
  // we'll need to unlock it as we the document exits fullscreen.  
  nsCOMPtr window = aDocument->GetWindow();  
  if (!window) {  
    return;  
  }  
  
  nsCOMPtr navigator;  
  window->GetNavigator(getter_AddRefs(navigator));  
  if (!navigator) {  
    return;  
  }  
  
  nsCOMPtr navigatorPointerLock = do_QueryInterface(navigator);  
  if (!navigatorPointerLock) {  
    return;  
  }  
  
  nsCOMPtr pointer;  
  navigatorPointerLock->GetMozPointer(getter_AddRefs(pointer));  
  if (!pointer) {  
    return;  
  }  
  
  // Unlock will bail early if not really locked  
  pointer->Unlock();

The value of early returns is that it's easier to read and less likely to contain bugs (i.e., variables can't change all of a sudden and break algorithm).  If you know that some code path is dead at a particular point, it's better to return right there.  After you've returned, it's much easier to deal with the remaining code, since you don't have to worry about hitting this spot due to state changes in a variable.  Plus, it's way easier to read when you don't have to visually trace the indenting so far to the right.

Here's a tip: return early, return often.

Show Comments