In my opinion, being able to write clean code is something that clearly separates a good developer from an average one. But it’s not something that you can turn on or off, it’s something that you achieve by adhering to many smaller techniques. And as you can probably guess, the early return is one of them.
The goal of the early return, as you can guess, is for your method to use the return keyword as soon as possible, meaning that you will probably have a bunch of returns through your method. It might sound confusing to a junior programmer, since you don’t know at a glance exactly where the method is returning, but believe me, it’s truly beneficial. Let’s take an example:
bool ShouldFireNuclearWeapon(PossibleTarget target)
{
if (target != null)
{
if (target.IsFromEnemyNation)
{
if (target.IsCarryingWeapon)
{
if (!target.IsCivillian)
{
return true;
}
else
{
return false;
}
}
if (target.LivingBeingInformation.NumberOfLegs == 2)
{
if (target.LivingBeingInformation.Height < 1.50)
{
return false;
}
else
{
return true;
}
}
}
}
return false;
}
Let’s suppose we’re developing the targeting system of our newly attack robot, and we’re currently working on how it chooses its target. By looking into the method above, we can’t clearly understand when it is returning true or false. And imagine that at some point, we would have to modify it. It will not be easy. But with some simple refactoring magic, we can make it much easier.
bool ShouldFireNuclearWeapon(PossibleTarget target)
{
if (target == null)
return false;
if (!target.IsFromEnemyNation)
return false;
if (target.IsCarryingWeapon)
return !target.IsCivillian;
if (target.LivingBeingInformation.NumberOfLegs == 2)
return target.LivingBeingInformation.Height > 1.50;
return false;
}
See? Definitely more clear. Still not crystal clear since we have to try to guess the meaning of some validations, like target.LivingBeingInformation.NumberOfLegs == 2, but that’s another topic about clean coding. But, still talking about the early return, there are even more reasons to adopt it. For example, let’s take a look at the following code:
void ShootThyEnemy(YupThatsATarget target)
{
PrepareLasers();
RaiseArm();
if (target != null)
Shoot();
}
We don’t know anything about the PrepareLasers() and RaiseArm() methods, but let’s suppose they take a long while to finish. Maybe even locking some resources, like a database table, for example. We would be putting our CPU effort to waste if, in the end, the target is null. Let’s do some refactoring:
void ShootThyEnemy(YupThatsATarget target)
{
if (target == null)
return;
PrepareLasers();
RaiseArm();
Shoot();
}
And there we go, now we will only run our methods if we actually have a target. Of course, one might argue that by the end of our lengthy methods, the target could be gone and we maybe should validate again, but let’s not delve into details.