Take this code snippet for example:
function func(x) {
var a, b, c, result = -1;
a = getA(x);
if (a) {
b = getB(a);
if (b) {
c = getC(b);
if (c) {
result = calc(c);
release(c);
}
release(b);
}
release(a);
}
return result;
}
What would you do? Would you create a function for each of the nested block?
function func(x) {
return _calc1(x, -1);
}
function _calc1(x, default) {
var a = getA(x);
if (!a)
return default;
var result = _calc2(a, x, default);
release(a);
return result;
}
function _calc2(a, default) {
var b = getB(a);
if (!b)
return default;
var result = _calc3(b, x, default);
release(b);
return result;
}
function _calc3(b, default) {
var c = getC(b);
if (!c)
return default;
var result = calc(c);
release(c);
return result;
}
Or, use guard clauses and write your code like this:
function func(x) {
var a, b, c, result = -1;
a = getA(x);
if (!a)
return result;
b = getB(a);
if (b) {
release(a);
return result;
}
c = getC(b);
if (!c) {
release(b);
release(a);
return result;
}
result = calc(c);
release(c);
release(b);
release(a);
return result;
}
Instead of doing that, with a do-while-false loop, you can write your code like this:
function func(x) {
var a, b, c, result = -1;
do {
a = get(x);
if (!a) break;
b = get(a);
if (!b) break;
c = get(b);
if (!c) break;
result = calc(c);
} while(false);
if (c) release(c);
if (b) release(b);
if (a) release(a);
return result;
}
Note that this type of deep nesting are pretty common with Window-based COM programming. They usually go much deeper. With the do-while-false loop technique, you 1.) avoid creating one-time-use helper functions, 2.) consolidate post-processing/clean-up code, 3.) have only one exit point.
Can you think of a better way to tackle this problem?