Disclaimer

The content of this blog is my personal opinion only. Although I am an employee - currently of Nvidia, in the past of other companies such as Iagination Technologies, MIPS, Intellectual Ventures, Intel, AMD, Motorola, and Gould - I reveal this only so that the reader may account for any possible bias I may have towards my employer's products. The statements I make here in no way represent my employer's position, nor am I authorized to speak on behalf of my employer. In fact, this posting may not even represent my personal opinion, since occasionally I play devil's advocate.

See http://docs.google.com/View?id=dcxddbtr_23cg5thdfj for photo credits.

Thursday, June 02, 2016

Principle of Smallest Scope

My mini-flame about a comment that might be interpreted as idiotically forbidding declaring a named subroutine inside a named subroutine inspired me to write this blurb about "The Principle of Smallest Scope".



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.

...
ret := big_complex_function_returning_struct(...)
print ret.to_string()
assert( not ret.is_error() )
next_function( ret.field1, "do more stuff" )
...
if idioms like this are used over and over, then I think you should restrict the scope of ret, if your language permits it:

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 () {
    ...
    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" )
    ...
}
E.g. it is good for a programming language to support scopes that are smaller than function scope.

    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: