I don't think I originated this principle, although I have practiced it for (ahem) decades, in (ahem) two different centuries. (ahem, probably scared off lots of headhunters: too old)
However, googling could not find me a reference for 'Principle of Smallest Scope'. Perhaps after I write this it will. (Perhaps also I just misremembered the name - "Principle of Least Scope"? "Principle of Most Restricted Scope"? If so, I will update this blog with a pointer to a better name.)
The Principle of Smallest Scope is much like the Law of Demeter, although that is more about object oriented design, whereas POSS applies to non-object systems. Both are just particular forms of information hiding.
So, what do I mean by the 'Principle of Smallest Scope'?
I mean that definitions, both named and anonymous, should be restricted to the smallest reasonable scope.
E.g. it is bad to use a global variable when a procedure local variable is sufficient.
E.g. within a procedure, you may have temporary variables - e.g. small local common subexpression elimination.
...if idioms like this are used over and over, then I think you should restrict the scope of ret, if your language permits it:
ret := big_complex_function_returning_struct(...)
print ret.to_string()
assert( not ret.is_error() )
next_function( ret.field1, "do more stuff" )
...
sub some_function () {
...
{
ret := big_complex_function_returning_struct(...)
print ret.to_string()
assert( not ret.is_error() )
next_function( ret.field1, "do more stuff" )
}
...
{
ret := another_big_complex_function_returning_struct(...)
print ret.to_string()
assert( not ret.is_error() )
another_next_function( ret.fieldA, "different but similar" )
}
...
}
rather than
sub some_function () {E.g. it is good for a programming language to support scopes that are smaller than function scope.
...
ret0 := big_complex_function_returning_struct(...)
print ret0.to_string()
assert( not ret0.is_error() )
next_function( ret0.field1, "do more stuff" )
...
ret1 := another_big_complex_function_returning_struct(...)
print ret0.to_string()
assert( not ret1.is_error() )
another_next_function( ret0.fieldA, "different but similar" )
...
}
Python fails this.
E.g. it is good to be allowed to declare named subroutines within named subroutines - and for it to be illegal to access the inner named subroutine outside of its enclosing scope. (At least, illegal by default.)
Perl fails this.
E.g. ditto nested classes. Lexically nested whatevers.
Now, I admit: masking of names can be confusing. It may be good to warn. It may also be good to require explicit override.
More later...
No comments:
Post a Comment