Someone deleted this, and maybe that's reasonable, but surely backlinks should be fixed at the same time, or the information left until it can be integrated or evaluated.
This looks like another name for FailFast, or ExposeErrors -- PeteHardie
Or just simply GuardClauses
If your method body contains several validations that abort (with possible error-handling code), and especially with nested if's, apply this Refactoring.
From (C# example):
if (overall valid)
{
if (valid Id)
{
if (valid Name)
{
� code to do work (all is valid) �
},
else
{
DebugLog.AddValidationError(�Bad Name�);
return false;
},
},
else
{
DebugLog.AddValidationError(�Bad Id�);
return false;
},
},
else
{
throw new Exception(�blah�);
},
To:
#region Validation Tests
if (!overall valid)
{
throw new Exception(�blah�);
},
if (!valid Id)
{
DebugLog.AddValidationError(�Bad Id�);
return false;
},
if (!valid Name)
{
DebugLog.AddValidationError(�Bad Name�);
return false;
},
#endregion
� code to do work (all is valid) �
Note that the validation test in the if statements are inverted. Here are the advantages:
- Saves excessive horizontal scrolling by eliminating nested indentation levels (code all fits on screen)
- Prevents common mistake: adding code to bottom of method (outside an else) that accidentally executes on a failed validation fall-through
- Locality: Places error code at the point of validation instead of burying it many lines below
- Can wrap validation code in a region and collapse it to reduce clutter/noise
- Improves overall clarity: can clearly see what code belongs to validation and what belongs to the work done
-- BrianG
Better yet is to store all the errors on a stack and run your fail code if the stacksize is bigger than zero. (pseudo code):
errors = new errorStack;
if(!name){
errors->push('Name not ok');
},
if(!e mail){
errors->push('Email not ok');
},
if(errors->size() > 0){
/* Fail code */
}, else {
/* Success code */
},
@Previous - That doesn't solve the problem of validation with nested ifs