Expressions and statements
ES.5
Keep scopes small
Reason
Readability. Minimize resource retention. Avoid accidental misuse of value.
Alternative formulation: Don't declare a name in an unnecessarily large scope.
Example
void use()
{
int i; // bad: i is needlessly accessible after loop
for (i = 0; i < 20; ++i) { /* ... */ }
// no intended use of i here
for (int i = 0; i < 20; ++i) { /* ... */ } // good: i is local to for-loop
if (auto pc = dynamic_cast<Circle*>(ps)) { // good: pc is local to if-statement
// ... deal with Circle ...
}
else {
// ... handle error ...
}
}
Example, bad
void use(const string& name)
{
string fn = name + ".txt";
ifstream is {fn};
Record r;
is >> r;
// ... 200 lines of code without intended use of fn or is ...
}
This function is by most measures too long anyway, but the point is that the resources used by fn and the file handle held by is are retained for much longer than needed and that unanticipated use of is and fn could happen later in the function. In this case, it might be a good idea to factor out the read:
Record load_record(const string& name)
{
string fn = name + ".txt";
ifstream is {fn};
Record r;
is >> r;
return r;
}
void use(const string& name)
{
Record r = load_record(name);
// ... 200 lines of code ...
}
Enforcement
- Flag loop variable declared outside a loop and not used after the loop
- Flag when expensive resources, such as file handles and locks are not used for N-lines (for some suitable N)