Encapsulation in Python

Ian Kelly ian.g.kelly at gmail.com
Sat Mar 12 11:44:45 EST 2016


On Fri, Mar 11, 2016 at 7:39 PM, Rick Johnson
<rantingrickjohnson at gmail.com> wrote:
> At run-time, i don't care how large a "module namespace" may
> be. Sometimes a module namespace will be small, with only a
> few exposed symbols, but sometimes, a module namespace will
> expose thousands of symbols.

Thousands, really? What system do you use to ensure that symbols don't
accidentally collide with one another? Because, you know, Python won't
check this for you even within a single file, unlike say C++ which
does allow splitting namespaces across multiple files. A linter might,
but not at runtime, and I don't expect it will be smart enough to
notice if the definitions are in different files.

>   (2) Create one file that will be the "mother-ship module",
>   and N files that will be the "satellite modules", and from
>   inside the mother-ship, import all the symbols from all
>   the satellites. Ha, but in reality, it's not that simple,
>   because state does not "magically" travel between modules!
>
>     ##########
>     # foo.py #
>     ##########
>     FOO_SHARED_STATE = "foo"
>     import _fooSatilite1
>     _fooSatilite1.FOO_SHARED_STATE = FOO_SHARED_STATE
>     from _fooSatilite1 import *
>     import _fooSatilite2
>     _fooSatilite2.FOO_SHARED_STATE = FOO_SHARED_STATE
>     from _fooSatilite2 import *
>     print 'This is the mother-ship called foo'
>     ...
>
>     ####################
>     # _fooSatilite1.py #
>     ####################
>     from _fooConstants import *
>     print 'This is foo-fighter1, reporting for duty'
>     print FOO_SHARED_STATE
>     ...
>
>     ####################
>     # _fooSatilite2.py #
>     ####################
>     from _fooConstants import *
>     print 'This is foo-fighter2, reporting for duty'
>     print FOO_SHARED_STATE
>     ...
>
> But i find both to be absurd. Writing all code in a single
> file might be fine for a toy module that contains a handful
> of functions or classes or vars, but once we start creating
> anything in the "professional size range", it will become
> an "editing nightmare" of epic proportions!
>
> But option two is no better, because once we cut and paste
> portions of the code into satellite files, we lose the
> ability to "easily share state". Then we're forced to start
> "hacking at the weeds" with import contortions and monkey
> patches, all the while, fearing the dreaded circular import.
>
>
> NO, THIS IS INSANITY!  WHAT WE NEED IS AN OPTION 3!
>
>  (3) Allow a programmer to define module space at will
>
>     ##########
>     # foo.py #
>     ##########
>     module foo
>     FOO_SHARED_STATE = "foo"
>     print 'This is the mother-ship called foo'
>     ...
>
>     ####################
>     # _fooSatilite1.py #
>     ####################
>     module foo
>     print 'This is foo-fighter1, reporting for duty'
>     print FOO_SHARED_STATE # NO MP REQUIRED!
>     ...
>
>     ####################
>     # _fooSatilite2.py #
>     ####################
>     module foo
>     print 'This is foo-fighter2, reporting for duty'
>     print FOO_SHARED_STATE # NO MP REQUIRED!
>     ...

Is this meant to be equivalent to the other example? In that example,
you have the two "satellite" modules being imported between the
definition of FOO_SHARED_STATE and the print. In this example, how on
Earth is Python supposed to know that after the FOO_SHARED_STATE line
it's supposed to switch to executing these other two files before
continuing on to the next statement?

More generally, what order do you expect these files to be executed in
when the "module" is imported? There must be some defined order,
because Python isn't magically capable of executing all three of them
simultaneously. If there's a defined order, then you should be able to
easily add explicit import statements at the tops of modules that
declare that order. So this is exactly the same as your "import
contortions" except that you want to make the reader (and the Python
interpreter) have to guess at the dependencies instead of making them
explicit.

> No need for import contortions, no need for monkey patching,
> but most importantly, no need for professional programmers
> to feel as though they are penchant little children, who
> need their "module diapers" wrapped for them by mommy
> Python, who, after popping one too many "mother's little
> helpers", has a nasty habit of wrapping our diapers too damn
> tight -- what a drag, it is, getting old...
>
>> 2) Clearly define which module is to be imported first. Then follow
>> it. When module b is imported, it should import module a. When module
>> a is imported, it *shouldn't* import module b until it's defined all
>> of its own members first. If module a depends on anything from module
>> b at import time, then refactor so it doesn't. This doesn't require
>> "contortions".
>
> That sounds simple in theory, but it breaks down quickly
> when you create "professional sized programs"

I find in interesting that you seem to be equating "very large" with
"professional". In my view, it's exactly the opposite. Anything very
large and so unorganized looks rather sloppy and unprofessional.


>> 3) Just put all your damn shared state in a class. There's nothing
>> stopping you from spreading out your class method definitions over
>> multiple files if you really want to, and it solves your import issue
>> by allowing everything to be imported before you even begin to set up
>> the shared state.
>
> Your words tell me that you have not written anything substantial.

I'll take your lack of substantive reply to mean "Huh, I never thought
of this approach that both solves my problem and improves the
structure of my code at the same time. Better hurl an insult to save
face!" Compliment accepted.

> I understand the importance of readability, but is usability
> of no concern to you? In fact, i would argue that, when
> *ROCK SOLID* professional interfaces are combined with
> proper documentation and strict adherence to style guides,
> there is no need to read source code.
>
> The only person who should be reading source, is a
> maintenance programmer. And if the code was designed
> properly, his job would be mostly just adding a feature here
> or there, or repairing a small bug here or there -- any code
> monkey can do that!

Yeah, you're so right. Professional software is write-once,
run-forever. Software requirements never change, and original designs
never have unforeseen consequences. "Maintenance" programmers exist as
some lower breed of programmer who are barely unable to understand how
loops work, much less invent thousands of distinct symbols to cram
into a single module so that they too can be considered professional
programmers.

</sarcasm>



More information about the Python-list mailing list