FAQ
PyMyth: Global variables are evil... WRONG!


============================================================
  Python's Global Hysteria:
============================================================
How many times have your heard or read the phrase: "Global
variables are evil"? Well if you've been a member of the
Python community, I'll bet you've heard or read it more than
most other community members.


In this thread, i want to get to the bottom of this whole
"global-phobia" thing once and for all, and hopefully help
you folks understand that globals are not all that bad --
when DESIGNED and USED correctly that is!


============================================================
  The denial of the 99%:
============================================================
Python has globals, but we just can't admit it!


The creators thought they would prevent the little
"PyPeople" from hurting themselves by "handicapping" our
globals in the form of "module level" globals.


But even the "module level" globals can be accessed
"globally" if the module they are contained in is imported
everywhere.


     import glomod
     glomod.var # Access
     global.var = newValue


Which leads me to the conclusion that the designers were
either naive or underestimated the chutzpah of this fine
community.


============================================================
  The Power of the 1%:
============================================================
Most of this "fear of globals" can be traced back to a
minority of naive coders who used globals haphazardly and
were hurt by them, <sarcasm>and now we ALL have to suffer
because future idiots need to be protected from themselves!
</sarcasm>


Too many times I've seen idiotic uses for globals.


One more atrocious example was "dialog return values" stored
as globals so the "dumb coder" could eaisly restore the
previous state of the dialog values between successive
calls.


Obviously the best solution would be for the dialog object
ITSELF to store (and restore) the values when necessary, but
alas, here i am again expecting people to create interfaces
that are consistent and logical. *rolls-eyes*


Of course we can only blame the dialog designer and not the
caller for this design flaw, but the caller still has no
excuse for globally storaging these values.


If the caller cannot repair the mistake by extending the
dialog object himself, then he can store the values within
the current module or class level scope. There is no excuse
for elevating this information to global scope.


However, there ARE justified uses of global variables!


============================================================
  Justifying Global Variables:
============================================================
Globals are justified when they are used to communicate
information between scopes that otherwise were meant to be
mutually exclusive. One good example would be package sub-
modules.


Now. Some might believe that the purity of namespaces
becomes tainted if they can be violently penetrated by
global variables. But again, they are falling back on gut
reactions fostered from years of brain washing. Yes, globals
can be bad (if misused), but for the most part they are
crucial to transferring information CLEANLY between isolated
namespaces


But even globals themselves are not good enough UNLESS we
engineer a "global hierarchy"!


============================================================
  From Flat to Nested == From Tricked to Bested:
============================================================
One of the shortcomings of the current implementation of
global variables is their inherent "flat" access nature.
There is no hierarchy of globals, and once all the good
names are taken, your screwed!


  "But Rick, even when we use globals, we don't need that many"


Only if you consider the single package that represents your
program, but what about the thousands of support libraries
with millions of lines of code that work in the background
to make your measly few thousand lines of code work? What
about all the globals that they have injected?


  "Never thought of that really"


Throwing out global names UNADORNED is folly. Could you
imagine telephone numbers without area codes?


  Hmm: Am i calling "Jim" in Beverly Hills California???


    california.beverlyhills.jim


  or "Jim" in "Spokane Washington"???


    washington.spokane.jim


You see, you need to QUALIFY these names not only to make
then unique, but also so the caller will understand who he
is calling.


Same goes for globals.

Search Discussions

  • Tim Daneliuk at Nov 12, 2013 at 2:47 am

    On 11/11/2013 08:06 PM, Rick Johnson wrote:
    Globals are justified when they are used to communicate
    information between scopes that otherwise were meant to be
    mutually exclusive.



    I think this is certainly the use case most people would suggest.


    But I think you may have missed the real reason most modern
    designers object to inter-module globals: The presence of
    such entities almost always means the code has been designed
    badly. Whether we're writing pristine OO code (cough, cough)
    or more traditional procedural stuff, information hiding
    is a good thing. When and where there is a need for modules
    (or programs, or machines, or "clouds", or interstellar space ...)
    to share information, my view is this is better done via some sort
    of interface/message passing mechanism. The more "things" that have
    to be shared across modules/programs/machines/clouds/space ... the more
    *brittle* the end system becomes.


    This problem is broader than just variables, BTW. It exists anytime you
    share *anything* across many computational components, especially in highly
    parallel and/or distributed systems. For example, RPCs tend to be lousy
    at building high scale distributed system because they usually have
    a call-and-wait semantic which will fail if the caller never responds.
    In this case the system is sharing the semantics of *time*. As a general
    matter, exactly-once asynchronous messaging tends to be a better implementation
    model here.


    Just my 2 cents worth. Interesting read. Thanks for taking the time
    --
    ----------------------------------------------------------------------------
    Tim Daneliuk tundra at tundraware.com
    PGP Key: http://www.tundraware.com/PGP/
  • Rick Johnson at Nov 12, 2013 at 4:46 am

    On Monday, November 11, 2013 8:47:09 PM UTC-6, Tim Daneliuk wrote:
    I think this is certainly the use case most people would
    suggest. But I think you may have missed the real reason
    most modern designers object to inter-module globals: The
    presence of such entities almost always means the code has
    been designed badly. Whether we're writing pristine OO
    code (cough, cough) or more traditional procedural stuff,
    information hiding is a good thing.

    Yes, and i agree. But you cannot "hide" everything. There
    will always be a need to share information.

    When and where there is a need for modules (or programs,
    or machines, or "clouds", or interstellar space ...) to
    share information, my view is this is better done via some
    sort of interface/message passing mechanism.

    But python modules can't be interfaces because interfaces
    should protect internal data, prevent external forces from
    meddling with internal state (EXCEPT via the rules of a
    predefined "contract"), hide dirty details from the caller,
    and have clearly defined access points.


       BUT PYTHON MODULES DON'T FOLLOW THIS DESIGN PATTERN!


    No, Python modules can be poked, prodded, and violated by
    any pervert who can spell the word "import".


    Attribute values can be reassigned and state can be
    externally manipulated resulting in all types of undefined
    behaviors -- that does not sound like an interface to me.


    So if python modules are importable everywhere, and mutable
    from everywhere, then python modules are merely addresses to
    a collection of global variables? And they're only
    interfaces "superficially"?


    So that leaves us with Python's current implementation of
    unofficial "global" variables implemented as "puesdo-
    interfaces" by module objects that are victims waiting to be
    violated.


    Interesting.


       IF IT WALKS LIKE A GLOBAL DUCK AND...
  • Chris Angelico at Nov 12, 2013 at 5:02 am

    On Tue, Nov 12, 2013 at 3:46 PM, Rick Johnson wrote:
    But python modules can't be interfaces because interfaces
    should protect internal data, prevent external forces from
    meddling with internal state (EXCEPT via the rules of a
    predefined "contract"), hide dirty details from the caller,
    and have clearly defined access points.

    BUT PYTHON MODULES DON'T FOLLOW THIS DESIGN PATTERN!

    No, Python modules can be poked, prodded, and violated by
    any pervert who can spell the word "import".

    And C++ objects can be poked by anyone who can do a pointer cast. And
    Java objects by anyone who notices that 'const' checks don't apply to
    byte-code. In fact, the only language I can think of that actually
    "prevent[s] external forces from meddling with internal state" is
    HQ9++, which follows the very best principles of data hiding.


    ChrisA
  • Ricardo Aráoz at Nov 12, 2013 at 10:15 am

    El 12/11/13 01:46, Rick Johnson escribi?:
    No, Python modules can be poked, prodded, and violated by any pervert
    who can spell the word "import". Attribute values can be reassigned
    and state can be externally manipulated resulting in all types of
    undefined behaviors --

    Nice!
    My code, my responsibility, my business.... not yours.

    that does not sound like an interface to me. So if python modules are
    importable everywhere, and mutable from everywhere, then python
    modules are merely addresses to a collection of global variables? And
    they're only interfaces "superficially"? So that leaves us with
    Python's current implementation of unofficial "global" variables
    implemented as "puesdo- interfaces" by module objects that are victims
    waiting to be violated. Interesting. IF IT WALKS LIKE A GLOBAL DUCK
    AND...

    Nice choice of words, "violated", "victims".... Really conductive to a
    balanced unprejudiced thought process.
  • Tim Chase at Nov 12, 2013 at 11:32 am

    On 2013-11-11 20:46, Rick Johnson wrote:
    Yes, and i agree. But you cannot "hide" everything. There
    will always be a need to share information.

    You may not be able to (or want to) hide everything, but sharing
    should at least happen over defined protocols (functions/methods).
    Otherwise, you wander off into the weeds of hackery and
    monkey-patching which makes maintaining the code a lot hairier.


    -tkc
  • Terry Reedy at Nov 13, 2013 at 1:20 am

    On 11/11/2013 11:46 PM, Rick Johnson wrote:


    No, Python modules can be poked, prodded, and violated by
    any pervert who can spell the word "import".

    Or by clever programmers.

    Attribute values can be reassigned and state can be
    externally manipulated

    Perhaps for good reasons.

    resulting in all types of undefined behaviors

    Not necessarily. Manipulation can also eliminate undefined behaviors.


    Suppose I want to test a Idle function that uses a tkinter.messagebox
    class to communicate with users. Perhaps the module has


    from tkinter.messagebox import askretrycancel


    The behavior of askretrycancel(*args) is undefined insofar as it depends
    on the arbitrary actions of a human user (it may even hang forever). In
    an automated test, there is no user, and it is difficult to simulate the
    eyes and fingers of one while leaving askretrycancel as it is.
    Monkeypatching with a mock solves this. Simplifying a bit, and leaving
    out details, I have done something like this.


    from mock_tkinter import mbox # mocks all messageboxes
    mock_arc = mbox()
    import mod
    mod.askretrycancel = mock_arc


    This makes mod.askretrycancel deterministic in that I can preload a
    response into mock_arc before calling the function or method in mod.
    (This simulates a user's fingers.) The mock also saves the values sent
    to it to see if they are what they should be. (This simulates a user's
    eyes.)


    --
    Terry Jan Reedy
  • Tim Daneliuk at Nov 14, 2013 at 12:17 am

    On 11/11/2013 10:46 PM, Rick Johnson wrote:
    On Monday, November 11, 2013 8:47:09 PM UTC-6, Tim Daneliuk wrote:
    I think this is certainly the use case most people would
    suggest. But I think you may have missed the real reason
    most modern designers object to inter-module globals: The
    presence of such entities almost always means the code has
    been designed badly. Whether we're writing pristine OO
    code (cough, cough) or more traditional procedural stuff,
    information hiding is a good thing.
    Yes, and i agree. But you cannot "hide" everything. There
    will always be a need to share information.
    When and where there is a need for modules (or programs,
    or machines, or "clouds", or interstellar space ...) to
    share information, my view is this is better done via some
    sort of interface/message passing mechanism.
    But python modules can't be interfaces because interfaces
    should protect internal data, prevent external forces from
    meddling with internal state (EXCEPT via the rules of a
    predefined "contract"), hide dirty details from the caller,
    and have clearly defined access points.

    BUT PYTHON MODULES DON'T FOLLOW THIS DESIGN PATTERN!



    I think this is an unfair criticism. You can do this in
    ANY language if you know how. For example, if I understand
    stack frames, I can write code that fiddles with local
    variables in compiled code. For that matter, if I understand
    pointers at the assembler level, I can probably do the same
    with globals.


    Global access/visibility is a matter of convenience - it's harder
    to do in a static compiled language and easier to do in a
    late bound, dynamic language. The fact that this is
    *possible* in Python doesn't speak to Python's fitness for
    any particular purpose nor does it speak to whether globals
    are a good- or bad idea. Anyone that knows enough to fiddle
    with the internal implementation of a module and or subvert
    global constants like math.pi, also know what they're doing
    is "perverse" and have to be willing to live with the side
    effects and consequences of such acts.


    I cut my teeth in this business writing realtime machine control
    software in assembly language (and PL/M!) where there was NO
    memory protection and everything - code, data, stack - was
    "global" in some sense, or at least could be made to be.
    We managed to routinely write highly reliable, blazingly
    fast code that didn't break, didn't bork, and did what it
    was supposed to. There's no reason to believe that Python
    programs cannot do the exact same thing (well, not the realtime
    part) with just as much robustness and correctness as those
    old asm programs.


    Programming well has far less to do with the language and has
    far more to do with the designer and coder...




    ----------------------------------------------------------------------------
    Tim Daneliuk tundra at tundraware.com
    PGP Key: http://www.tundraware.com/PGP/
  • Rick Johnson at Nov 14, 2013 at 2:25 am

    On Wednesday, November 13, 2013 6:17:22 PM UTC-6, Tim Daneliuk wrote:
    But python modules can't be interfaces because interfaces
    should protect internal data, prevent external forces from
    meddling with internal state (EXCEPT via the rules of a
    predefined "contract"), hide dirty details from the caller,
    and have clearly defined access points.
    BUT PYTHON MODULES DON'T FOLLOW THIS DESIGN PATTERN!
    I think this is an unfair criticism. You can do this in
    ANY language if you know how. For example, if I understand
    stack frames, I can write code that fiddles with local
    variables in compiled code. For that matter, if I understand
    pointers at the assembler level, I can probably do the same
    with globals.

    And if i understand file systems, and i have access to your
    computer, i can delete the contents of your hard disc :-). We
    can take this analogy all the way to it's absurd conclusions,
    but we have not proven anything.

    Programming well has far less to do with the language and
    has far more to do with the designer and coder...

    I very much agree.
  • Jongiddy at Nov 12, 2013 at 2:12 pm
    On Tuesday, November 12, 2013 2:06:09 AM UTC, Rick Johnson wrote:

    ============================================================

    Justifying Global Variables:

    ============================================================

    Globals are justified when they are used to communicate

    information between scopes that otherwise were meant to be

    mutually exclusive. One good example would be package sub-

    modules.

    Can you please give an example where having a module provide a global variable would work better than any of:
    1. providing a module function to change the operation of my module
    2. providing a class with a method to change the operation of an instance
    3. providing an additional parameter to module functions / instance methods to change operation
    4. providing additional module functions / instance methods to perform different operations
  • Rick Johnson at Nov 12, 2013 at 3:05 pm

    On Tuesday, November 12, 2013 8:12:10 AM UTC-6, jongiddy wrote:


    Can you please give an example where having a module
    provide a global variable would work better than any of:
    [snip]

    Well my point is that the attributes of any Python module
    are "emulating" globals already. The fact that we have to
    mutate them via a "psuedo" interface makes us "falsely"
    believe we are using an interface -- but we aren't!


      PYTHON MADE ACCESSING GLOBAL VARIABLES MORE DIFFICULT!


    As example. I could import the math module and start
    fiddling with attributes. Let's say for example i can change
    the value of math.pi. Most people would probably say "what's
    the problem with that?", here, let me show you.


         # mod1.py
         print "mod1.py"
         import math
         math.pi = "tasty"


         # mod2.py
         print "mod2.py"
         import math
         print ' value of math.pi is:', math.pi
         radius = 10
         math.pi * radius


         #modmain.py
         import mod1
         import mod2
         print dir(mod1)
         print dir(mod2)


    When you run "modmain.py" you will see that not only have we
    changed the global variable "pi" to a string, but thanks to
    a dumb overloading of the multiply operator, python will
    happily give use the wrong answer -- but that's another
    problem, let's stay focused on the "global" problem for now!


    When i type "math.pi", i "feel" as though i'm accessing an
    interface, BUT I'M NOT! If i was indeed accessing a TRUE
    interface, the interface would have thrown a Type error for
    attempting to assign a value of type string to what should
    only be a float. The interface would have protected it's
    internal data from corruption, but it didn't.


       BECAUSE IT'S NOT AN INTERFACE!


    It's just a dumb namespace with no exposed hooks to control
    it's underlying behavior.


       MY POINT IS:


    Python designers act like globals are SO evil, but then they
    give us modules which are containers for global variables,
    and now the globals contained within those modules are
    wolves in sheep's clothing. Are they just trying to fool
    themselves, or fool us?


       FOOD FOR THOUGHT:


    What's worse? A wolf? Or a wolf in sheep's clothing?
  • Jongiddy at Nov 12, 2013 at 3:33 pm

    On Tuesday, November 12, 2013 3:05:25 PM UTC, Rick Johnson wrote:


    When i type "math.pi", i "feel" as though i'm accessing an

    interface, BUT I'M NOT!

    I'm not sure where you get the feeling you're accessing an interface. If I typed this, I would feel like I was trying to change a fundamental constant.


    You have just demonstrated that going into other modules and changing their attributes (whether they are variables, functions or classes) is generally a BAD idea, and I don't think I've ever seen anyone recommend doing this, except possibly as a workaround or for debugging purposes.


    On the other hand, you initially suggested that modifying globals contained within namespaces (i.e. modules) is a good way to communicate between modules. That is, you suggested in your initial post that going into other modules and changing their attributes is a GOOD idea.


    This inconsistency is why I was asking for a good example (i.e. a realistic example where the use of global variables provides the best solution).


    Just because a tool allows you to do something does not make it a good idea. Try this paraphrase of your last post: Ladder designers act like standing on the top rung is SO evil, but then they give us ladders with a top rung, Are they just trying to fool themselves, or fool us?
  • Rick Johnson at Nov 12, 2013 at 5:00 pm

    On Tuesday, November 12, 2013 9:33:50 AM UTC-6, jongiddy wrote:
    I'm not sure where you get the feeling you're accessing an
    interface.

    Because the constant PI should never change. Sure we can
    argue about granularity of PI, but that argument has no
    weight on the fact that PI should be a constant.


    By placing PI in the module "math", we are creating a pseudo
    interface. We (the creators) are "assuming" that PI will be a
    constant and never change, and the caller is assuming that
    pi will remain static, but not only can it be mutated, it
    can be mutated globally.


    math.pi is neither a constant nor a local module attribute,
    math.pi is really a global variable. This is true not only
    for math.pi, but ALL attributes of ALL python modules.

    If I typed this, I would feel like I was trying
    to change a fundamental constant. You have just
    demonstrated that going into other modules and changing
    their attributes (whether they are variables, functions or
    classes) is generally a BAD idea, and I don't think I've
    ever seen anyone recommend doing this, except possibly as
    a workaround or for debugging purposes. On the other hand,
    you initially suggested that modifying globals contained
    within namespaces (i.e. modules) is a good way to
    communicate between modules.

    You missed my point: only IF python modules were TRUE
    interfaces. It's not a good idea under python's current
    implementation of modules. My thread is intended to
    underscore this very design flaw.

    This inconsistency

    There is no inconsistency in my logic, quite the contrary.


    I think you're having difficulty following along because
    you've been brainwashed by Python for too long. You've
    falsely believed that Python does not have globals, but
    it does! You just have to mutate then via a pseudo
    interface.

    is why I was asking for a good example (i.e.
    a realistic example where the use of global variables
    provides the best solution).

    I gave a good example in my very first post:


         RR: "Globals are justified when they are used to
         [share] information between scopes that otherwise
         were meant to be mutually exclusive. One good
         example would be package sub-modules."

    Just because a tool allows you to do something does not
    make it a good idea. Try this paraphrase of your last
    post: Ladder designers act like standing on the top rung
    is SO evil, but then they give us ladders with a top rung,
    Are they just trying to fool themselves, or fool us?

    EXACTLY. And whilst your comparison is both intelligent and
    funny, you're just re-iterating my point!


    We have all been brainwashed by authorities. First they
    give us rules, then they give us the power to break
    those rules. If standing on the top rung is SO
    dangerous, then don't manufacture your ladders with top
    rungs. Else, shut up about it!


       "THOU SHALT NOT KILL"


    Well i can't live WITH the B!@$%!!!


       "THOU SHALT NOT COMMIT ADULTERY"


    Then why create me with a unquenchable desire for sex?


       "THOU SHALT NOT TAKE THE LORDS NAME IN VAIN"


    GOD DAMMIT! Stop making all these opposing rules.


    So the designers detest globals huh? But python module
    attributes are really global because they can be accessed
    and mutated ANYWHERE!". This enigma leads to two logical
    design philosophies: (anything else is folly)


        1. Accept that globals are useful, and make them
           available through a "real" global syntax, not
           some attribute of a module that "appears" to be
           local, but in reality is global. Then prevent
           external mutation of module attributes directly,
           and instead, require that mutation must follow a
           contract defined by internal module "setter"
           functions.


        2. Remain convinced that global mutation is evil
           and prevent mutation of all python module
           attributes. You can import modules, but you can't
           mutate their contents.


    THIS IS HOW YOU DESIGN FOR CONSISTENCY, NOT HYPOCRISY!


    @LanguageDesigners: But whatever you do, don't hide globals
    behind pseudo interfaces, because then you have created
    something worse than a global; you've created a global in
    sheep's clothing. And you're a hypocrite.
  • Rick Johnson at Nov 12, 2013 at 5:42 pm
    On Tuesday, November 12, 2013 11:00:37 AM UTC-6, Rick Johnson wrote:
    [snip]
    We have all been brainwashed by authorities. First they
    give us rules, then they give us the power to break
    those rules.

    The devil himself said it best:


       http://www.youtube.com/watch?v=RGR4SFOimlk


    Hmm. How do we humans cope with all these opposing rules? If
    we created an AI with all the ridiculous, convoluted and
    opposing rules that we humans live with on a daily basis, it
    would blow chunks.


    How do our minds possibly cope with such illogical rules
    without blowing chunks?


    We cope by re-inventing reality. We cope by convincing
    ourselves that truths are not true and lies are true.


    We cope by designing languages that obfuscate globals behind
    pseudo interfaces so we can get farm fuzzy feelings in our
    tummy, then we can "secretly" break the rule when non-one is
    looking.


    By doing this we convince ourselves that we are "pure".


    HUMANS: What a pathetic bunch of slaves!


      http://www.youtube.com/watch?v=PFdmAgA_Gfo
  • Tim Chase at Nov 12, 2013 at 5:45 pm

    On 2013-11-12 09:00, Rick Johnson wrote:
    Because the constant PI should never change. Sure we can
    argue about granularity of PI, but that argument has no
    weight on the fact that PI should be a constant.

    By placing PI in the module "math", we are creating a pseudo
    interface. We (the creators) are "assuming" that PI will be a
    constant and never change, and the caller is assuming that
    pi will remain static, but not only can it be mutated, it
    can be mutated globally.

    But the module-scoping of "globals" is perfectly valid:

    print(math.PI)
      3.1415926535897932
    print(Magnum.PI)
      "Tom Selleck"


    As an example from the stdlib of setting globals via a protocol,
    locale.setlocale() does exactly this. So I'm not sure why you have
    your knickers in a knot. Module-level items can be accessed
    globally (though often a bad idea, or at least you have to beware of
    side-effects where other things might break), and if you don't like
    the "modules are not objects", someone in this thread already showed
    you that you can insert objects/classes into the sys.modules and get
    full getter/setter functionality with minimal trouble.


    Finally, we're all (mostly) consenting adults here. If I want to be
    an idiot and


       math.PI = 3.14


    and suddenly stuff breaks, I get to keep all the pieces my breakage
    caused.


    -tkc
  • Jongiddy at Nov 12, 2013 at 10:41 pm

    On Tuesday, November 12, 2013 5:00:37 PM UTC, Rick Johnson wrote:

    1. Accept that globals are useful, and make them

    available through a "real" global syntax, not

    some attribute of a module that "appears" to be

    local, but in reality is global. Then prevent

    external mutation of module attributes directly,

    and instead, require that mutation must follow a

    contract defined by internal module "setter"

    functions.



    2. Remain convinced that global mutation is evil

    and prevent mutation of all python module

    attributes. You can import modules, but you can't

    mutate their contents.
    From your first post, I take it you're not keen on option #2.

    For #1, module globals are exactly the hierarchically namespaced globals that you desire in your first post, except they are variables, not get/set handlers (which is what I take you to mean by an "interface").


    Why not create a PEP to provide handlers for module attributes? You could base it on PEP 213, which describes the same feature for classes.


    As a bonus, this would trivially support option #2 (e.g. non-mutable math.pi) by raising an exception for the set operator.
  • Rick Johnson at Nov 13, 2013 at 2:45 am

    On Tuesday, November 12, 2013 4:41:34 PM UTC-6, jongiddy wrote:
    On Tuesday, November 12, 2013 5:00:37 PM UTC, Rick Johnson wrote:
    1. Accept that globals are useful, and make them
    available through a "real" global syntax, not
    some attribute of a module that "appears" to be
    local, but in reality is global. Then prevent
    external mutation of module attributes directly,
    and instead, require that mutation must follow a
    contract defined by internal module "setter"
    functions.
    2. Remain convinced that global mutation is evil
    and prevent mutation of all python module
    attributes. You can import modules, but you can't
    mutate their contents.
    From your first post, I take it you're not keen on option #2.

    That is correct, i prefer to use REAL interfaces.

    For #1, module globals are exactly the hierarchically
    namespaced globals that you desire in your first post,

    Agreed.

    except they are variables, not get/set handlers (which is
    what I take you to mean by an "interface").

    Yes, python modules expose ALL members publicly and have no
    support for contractual interfacing.

    Why not create a PEP to provide handlers for module
    attributes? You could base it on PEP 213, which describes
    the same feature for classes.

    I would love to see modules expand to something more than
    mere "boxes to stuff variables". But then again, modules
    are not going to provide the ease of access that globals
    demand due to the import problem.


    Modules will not be a good place to store globals because
    modules must be imported and globals should never need
    importing.


    I've just released a module on Python-list called "G.py"
    that does exactly what i propose. It's not perfect, but i
    think you'll understand what i'm proposing after testing
    it.

    As a bonus, this would trivially support option #2 (e.g.
    non-mutable math.pi) by raising an exception for the set
    operator.

    "math.pi" should be "math.PI". and PI should be a CONSTANT.
    And not just a pseudo constant, but a REAL constant that
    cannot be changed.
  • Tim Chase at Nov 13, 2013 at 3:22 am

    On 2013-11-12 18:45, Rick Johnson wrote:
    "math.pi" should be "math.PI".

    It's a real shame that this fails:

    math.PI = math.pi

    oh...wait...

    and PI should be a CONSTANT. And not just a pseudo constant, but a
    REAL constant that cannot be changed.

    How much precision do you want? Perhaps you really do want do just
    use because you know you only have 2-3 places of precision in your
    other numbers:


       math.pi = 3.14


    Or maybe you want to monkey-patch in a fraction/decimal instead for
    greater precision:


      math.pi = decimal.Decimal('3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679')


    It comes back to Python being a language for consenting adults.


    -tkc
  • Andrew Cooper at Nov 13, 2013 at 10:00 pm

    On 13/11/2013 02:45, Rick Johnson wrote:
    "math.pi" should be "math.PI". and PI should be a CONSTANT.
    And not just a pseudo constant, but a REAL constant that
    cannot be changed.

    And what do you do when the wizards bend space-time to make PI exactly
    3, for the ease of other calculations when building a sorting machine?


    Does usenet start delivering these posts in the past/future?


    I suspect real python programmers will be able to feel quite smug when
    they can change the value of math.pi to suit the situation.


    ~Andrew
  • Rick Johnson at Nov 14, 2013 at 2:16 am

    On Wednesday, November 13, 2013 4:00:15 PM UTC-6, Andrew Cooper wrote:
    And what do you do when the wizards bend space-time to
    make PI exactly 3, for the ease of other calculations when
    building a sorting machine?

    Are you telling me that these wizards can't be bothered to
    write the integer "3"? They have to reassign math.pi instead?


    Look if you need some other granularity of PI besides
    what's offered in math.PI, then do your own calculation.


    The last thing you want to do is create a variable when a
    constant is what you need.
  • Alister at Nov 12, 2013 at 2:32 pm
    On Mon, 11 Nov 2013 18:06:09 -0800, Rick Johnson wrote:

    In this thread, i want to get to the bottom of this whole
    "global-phobia" thing once and for all, and hopefully help you folks
    understand that globals are not all that bad -- when DESIGNED and USED
    correctly that is!

    it is the final part of that statement that is important


    As a generality "Avoid Globals" is not a bad "rule".
    there may be some occasions when breaking this rule may be acceptable but
    it requires great experience & detailed knowledge to know when this is
    the right thing to do.


    As an analogy music has may general rules that musicians are wise to
    follow.
    Some pieces of music that break these rules are great because they have
    broken the rules but most are not. those that are great are great because
    the musician in question understands the reasons for the rules & how
    breaking them will affect the end product, the ones that are bad are
    because the musician does not know enough about music to even know the
    rule exists.










    --
    Immutability, Three Rules of:
      (1) If a tarpaulin can flap, it will.
      (2) If a small boy can get dirty, he will.
      (3) If a teenager can go out, he will.
      (3a) If a teenager cant go out, he will. :-)
  • Chris Angelico at Nov 12, 2013 at 3:22 pm

    On Wed, Nov 13, 2013 at 1:32 AM, Alister wrote:
    As an analogy music has may general rules that musicians are wise to
    follow.
    Some pieces of music that break these rules are great because they have
    broken the rules but most are not. those that are great are great because
    the musician in question understands the reasons for the rules & how
    breaking them will affect the end product, the ones that are bad are
    because the musician does not know enough about music to even know the
    rule exists.

    Agreed. Pieces of music that violate the rules arbitrarily are just
    annoying to try to play (and nearly impossible for the church to
    follow), but when you find those really brilliant pieces that do
    something special (Sir Arthur Sullivan, I'm looking at you -
    especially having just been reading the booklet that came with the new
    Beauty Stone recording), it's magnificent.


    Global variables basically don't exist in Python. You have per-module
    state. And if you start monkey-patching, you're fiddling with someone
    else's module. It's all fun and games till someone loses a function...


    sys.stdout.write=None


    ChrisA
  • Rhodri James at Nov 13, 2013 at 11:42 pm

    On Tue, 12 Nov 2013 02:06:09 -0000, Rick Johnson wrote:


    PyMyth: Global variables are evil... WRONG!

    That's not a PyMyth. It's a CompSciMyth, or to be more accurate a good
    general Software Engineering guideline regardless of language. Like all
    guidelines it can be broken, but people who break it should do so
    knowingly, aware that they have created potential problems for themselves.

    ============================================================
    The denial of the 99%:
    ============================================================
    Python has globals, but we just can't admit it!

    A different subject entirely, but no more accurately stated.


    [snip]
    But even the "module level" globals can be accessed
    "globally" if the module they are contained in is imported
    everywhere.

    Remember when I said that guidelines can be broken?

    Globals are justified when they are used to communicate
    information between scopes that otherwise were meant to be
    mutually exclusive. One good example would be package sub-
    modules.

    Sometimes, yes. As long as you don't mind not being thread-safe, etc,
    etc. If you've designed your interface, you're probably fine. If you've
    throw it together with globals because it's the easy way, you're about to
    find out why the guideline you're breaking is a good one.

    "But Rick, even when we use globals, we don't need that many"

    Only if you consider the single package that represents your
    program, but what about the thousands of support libraries
    with millions of lines of code that work in the background
    to make your measly few thousand lines of code work? What
    about all the globals that they have injected?

    Didn't you just say that Python globals are really module-level globals?
    Isn't this a strawman you've already disallowed? It sounds to me like
    you're complaining that Python is ahead of the curve here :-)


    --
    Rhodri James *-* Wildebeest Herder to the Masses
  • Mark Lawrence at Nov 13, 2013 at 11:57 pm

    On 13/11/2013 23:42, Rhodri James wrote:
    On Tue, 12 Nov 2013 02:06:09 -0000, Rick Johnson
    wrote:
    PyMyth: Global variables are evil... WRONG!
    That's not a PyMyth. It's a CompSciMyth, or to be more accurate a good
    general Software Engineering guideline regardless of language. Like all
    guidelines it can be broken, but people who break it should do so
    knowingly, aware that they have created potential problems for themselves.

    A quote from a colleage of mine circa 1991 "Real time programming is
    easy, just make all the data global". There you are everybody, problem
    solved :)


    --
    Python is the second best programming language in the world.
    But the best has yet to be invented. Christian Tismer


    Mark Lawrence
  • Steven D'Aprano at Nov 14, 2013 at 1:09 am

    On Wed, 13 Nov 2013 23:42:24 +0000, Rhodri James wrote:


    On Tue, 12 Nov 2013 02:06:09 -0000, Rick Johnson
    wrote:
    PyMyth: Global variables are evil... WRONG!
    That's not a PyMyth. It's a CompSciMyth, or to be more accurate a good
    general Software Engineering guideline regardless of language.

    To be precise, it's not a myth at all.


    Just because there are occasional medical uses for digitalis doesn't make
    it a myth that it is deadly poison. Just because there are occasional
    programming uses for global variables doesn't make it a myth that they
    are poor practice and lead to hard-to-maintain, unsafe, buggy code.



    Like all
    guidelines it can be broken, but people who break it should do so
    knowingly, aware that they have created potential problems for
    themselves.

    Absolutely correct.



    ============================================================
    The denial of the 99%:
    ============================================================ Python has
    globals, but we just can't admit it!
    A different subject entirely, but no more accurately stated.

    Completely inaccurately stated. It certainly isn't true that "99%" of
    people (who exactly? Rick doesn't say) claim that Python has no globals.
    That would be a stupid thing to say for a language with a "global"
    keyword, a "globals" function, and a built-in module that is shared
    across the entire process.



    [snip]
    But even the "module level" globals can be accessed "globally" if the
    module they are contained in is imported everywhere.
    Remember when I said that guidelines can be broken?

    I think you know the following, but for anyone else reading...


    Just because a module global alpha.spam is accessible to anything that
    imports the module doesn't make it a process-wide global. The ability to
    do this:


    import alpha
    alpha.spam = 23


    does not make "spam" a process-wide global. It just means that attribute
    access on the module object is the supported interface for manipulating
    names in namespaces which are modules.


    There is very little practical difference apart from convenience between
    directly manipulating attributes as above, and using a setter function
    like "setattr(alpha, 'spam', 23)". Python tries to avoid boilerplate.
    Since manipulating attributes is useful, a philosophy of consenting
    adults applies and we have direct access to those attributes, with an
    understanding that we should use this power with care. With great power
    comes great responsibility -- if you're going to reach inside another
    module and manipulate things, you ought to know what you're doing.


    One of the numerous problems with process-wide globals is that there's no
    encapsulation and consequently one package's use of "spam" clobbers
    another package's use of "spam" for a different purpose. But that's not
    the case here: alpha's "spam" is separate from module omega's "spam"
    variable.


    To give an analogy: just because I can walk through the door of number 23
    Alpha Street and rummage through their fridge, and walk through the door
    of number 42 Omega Road and do the same, doesn't mean that the two
    fridges are actually the same fridge.






    --
    Steven
  • Rick Johnson at Nov 14, 2013 at 3:22 am

    On Wednesday, November 13, 2013 7:09:42 PM UTC-6, Steven D'Aprano wrote:
    On Wed, 13 Nov 2013 23:42:24 +0000, Rhodri James wrote:
    On Tue, 12 Nov 2013 02:06:09 -0000, Rick Johnson wrote:
    Python has globals, but we just can't admit it!
    A different subject entirely, but no more accurately stated.
    Completely inaccurately stated. It certainly isn't true
    that "99%" of people claim that Python has no globals.
    That would be a stupid thing to say for a language with a
    "global" keyword,

    Yeah, a "global" keyword that extends access ONLY as far as
    module level scope -- hardly a *true* global.

    a "globals" function,

    Yeah, a "globals function" that returns the MODULE LEVEL
    globals symbol table.

    and a built-in module that is shared across the entire
    process.

    Now your thinking clearly. This is where Python's dirty
    little "secret globals" live.

    Just because a module global alpha.spam is accessible to
    anything that imports the module doesn't make it a
    process-wide global. The ability to do this: import alpha
    alpha.spam = 23 does not make "spam" a process-wide
    global.

    Oh lord, back to the fuzzy logic again :(

    It just means that attribute access on the module object
    is the supported interface for manipulating names in
    namespaces which are modules.

    HUH? Was this last sentence an attempt to distract? We are
    all quite aware that DOT access is the interface for
    accessing module members, but what the hell does that have
    to do with "process wide globals"?


    No, your not going to so easily fool this audience with
    slight of hand! In your generalized code example:


         import alpha
         alpha.spam = 23


    Yes. "spam" is an attribute of module "alpha", however, it is
    also a global variable. Why?


       BECAUSE "alpha.spam" CAN BE MUTATED FROM ANYWHERE!

    There is very little practical difference apart from
    convenience between directly manipulating attributes as
    above, and using a setter function like "setattr(alpha,
    'spam', 23)". Python tries to avoid boilerplate.

    Here you go again. Steven, we are ALL quite aware of these
    facts, how is "setattr" germane to my complaints about globals?

    Since manipulating attributes is useful, a philosophy of
    consenting adults applies and we have direct access to
    those attributes,

    We don't have "direct access", but access is an import away.

    with an understanding that we should use this power with
    care. With great power comes great responsibility -- if
    you're going to reach inside another module and manipulate
    things, you ought to know what you're doing.

    Yes we must be careful, because these attributes are
    ACTUALLY global. The fact that you have to use an import
    statement to reach them does not alter the fact that they are
    globally mutable.

    One of the
    numerous problems with process-wide globals is that
    there's no encapsulation and consequently one package's
    use of "spam" clobbers another package's use of "spam" for
    a different purpose.

    Exactly. That's why globals should be used intelligently.
    There are many methods of creating an intelligent ordering
    of global names so they don't clash. One of the most
    simplistic is to tag all names with a prefix.


    The best method is to have a namespace for globals that is
    available everywhere WITHOUT import and accessed via a
    single letter (you could emulate this now in Python by
    injecting a namespace into sys.modules). In this manner,
    globals will be both easily accessible, qualified (no need
    for prefixes), and available WITHOUT messy imports

    But that's not the case here: alpha's "spam" is separate
    from module omega's "spam" variable. To give an analogy:
    [snip analogy]

    Steven you're going off into "la-la land" man. Are you
    suggesting that because two modules can contain the same
    name that module attributes are not global?


    I love how you support the duck typing paradigm UNTIL it
    interferes with your argument. Sure, under Python's current
    implementation of "globally mutable module attributes" you
    can have the same name stored in different modules all with
    different values, but they're still GLOBALS!


    Because I can reach in and access them OR mutate them from
    ANYWHERE! That's the very definition of a "globally
    accessible variable" (aka: global variable)


         AND THIS IS WERE THE HYPOCRISY COMES IN.


    Since python modules have no set/get interface restrictions,
    ALL attributes are globals!
  • Chris Angelico at Nov 14, 2013 at 3:29 am

    On Thu, Nov 14, 2013 at 2:22 PM, Rick Johnson wrote:
    Yeah, a "global" keyword that extends access ONLY as far as
    module level scope -- hardly a *true* global.

    I have yet to see any language that gives true globals. At very best,
    they're just process-wide! Honestly. How am I supposed to write code
    that accesses variables running on my New York server?


    Now, of course, if I had a server on Mars, that would be completely
    different. They're only globals, after all.


    ChrisA
  • Roy Smith at Nov 14, 2013 at 4:33 am
    In article <mailman.2580.1384399784.18130.python-list@python.org>,
      Chris Angelico wrote:

    I have yet to see any language that gives true globals. At very best,
    they're just process-wide! Honestly. How am I supposed to write code
    that accesses variables running on my New York server?

    Any one of a slew of remote procedure call protocols. These days, the
    cool kids are using REST, but people have been doing RPC-ish things ever
    since the first guy to connect two computers with a piece of wire.


    Wait, aren't you the guy who's into MUDs?
  • Rick Johnson at Nov 14, 2013 at 4:40 am

    On Wednesday, November 13, 2013 10:33:22 PM UTC-6, Roy Smith wrote:
    Wait, aren't you the guy who's into MUDs?

    Yes he is.


    But that's his second favorite hobby.


    His first is filling the "Devils Advocate" slot when
    Steven is too busy -- doing WHATEVER Steven does when
    he's not here. God only knows.
  • Chris Angelico at Nov 14, 2013 at 4:53 am

    On Thu, Nov 14, 2013 at 3:33 PM, Roy Smith wrote:
    In article <mailman.2580.1384399784.18130.python-list@python.org>,
    Chris Angelico wrote:
    I have yet to see any language that gives true globals. At very best,
    they're just process-wide! Honestly. How am I supposed to write code
    that accesses variables running on my New York server?
    Any one of a slew of remote procedure call protocols. These days, the
    cool kids are using REST, but people have been doing RPC-ish things ever
    since the first guy to connect two computers with a piece of wire.

    Wait, aren't you the guy who's into MUDs?

    Yeah, I am. But there's this annoying difficulty with accessing
    variables. I have to send messages around the world and get responses
    back, I can't just type "global foo" and have foo be the same thing
    here and everywhere else. I mean, it's called "global" for a reason,
    why can't it be the same "foo" for every single process in the world?


    Or if it's okay for "globals" to not be globally shared, then why is
    it a problem for them to be per-module?


    ChrisA
  • Steven D'Aprano at Nov 14, 2013 at 6:25 am

    On Wed, 13 Nov 2013 23:33:22 -0500, Roy Smith wrote:


    In article <mailman.2580.1384399784.18130.python-list@python.org>,
    Chris Angelico wrote:
    I have yet to see any language that gives true globals. At very best,
    they're just process-wide! Honestly. How am I supposed to write code
    that accesses variables running on my New York server?
    Any one of a slew of remote procedure call protocols. These days, the
    cool kids are using REST, but people have been doing RPC-ish things ever
    since the first guy to connect two computers with a piece of wire.

    Nice Devil's Advocacy :-)


    But of course, there are differences between the two situations. In a RPC,
    you have to use a defined interface to reach across the wire, so to
    speak, rather than have the two machines intimately coupled in a single
    namespace.


    It is true that you can write RPC code that is highly coupled. Such
    highly coupled code is harmful whether it occurs due to global variables
    or via RPC calls or some other mechanism. But the difference is you have
    to work at it to write such highly coupled code with RPC calls, while
    with single-process globals such coupling occurs naturally without effort.




    --
    Steven
  • Unknown at Nov 14, 2013 at 9:41 am

    On Thu, 14 Nov 2013 14:29:41 +1100, Chris Angelico wrote:


    On Thu, Nov 14, 2013 at 2:22 PM, Rick Johnson
    wrote:
    Yeah, a "global" keyword that extends access ONLY as far as module
    level scope -- hardly a *true* global.
    I have yet to see any language that gives true globals. At very best,
    they're just process-wide! Honestly. How am I supposed to write code
    that accesses variables running on my New York server?

    Now, of course, if I had a server on Mars, that would be completely
    different. They're only globals, after all.

    ChrisA

    + networking computers on Mars is impossible (with TCP/IP at least)
  • Rick Johnson at Nov 14, 2013 at 2:10 am

    On Wednesday, November 13, 2013 5:42:24 PM UTC-6, Rhodri James wrote:
    On Tue, 12 Nov 2013 02:06:09 -0000, Rick Johnson wrote:
    PyMyth: Global variables are evil... WRONG!
    That's not a PyMyth. It's a CompSciMyth, or to be more
    accurate a good general Software Engineering guideline
    regardless of language. Like all guidelines it can be
    broken, but people who break it should do so knowingly,
    aware that they have created potential problems for
    themselves.

    You speak as if using globals are inhabited by gremlins
    just wanting to get out and run a muck. There are no
    "inherent" problems in the global interface design except
    those that programmer inserts himself.


    Real global variable interfacing is no different than
    python object member interfacing, or module interfacing,
    except that the latter two are encapsulated by inside a
    namespace, and the former (historically) are unprotected and
    available everywhere; hence the name "global" :-)


    With Python, i can still reassign a value to class attribute
    and break code that depends on that attribute, of course,
    doing so is not a good idea; but it's allowed nonetheless!


    The programmer can break ANY interface in Python, be it
    accessing a module attribute he shouldn't touch or via a
    "real global" variable (if Python had that functionality).


    So that renders this whole argument of "global gremlins" as
    FUD. The gremlins don't exist until the programmer creates
    them. Just because one programmer is unable to create a
    logical global implementation, does not mean another cannot.


    All you need to do is adopt the principles of consistency.


    But i'm not here to convince you that globals are correct
    for you, nor do i want you to use them if you feel
    uncomfortable (lord knows there's enough bad code
    circulating already!) i just want people to stop propagating
    this myth that globals are evil.


    And i also want to point out the hypocrisy of Python's
    design. Python DOES have globals
  • Steven D'Aprano at Nov 14, 2013 at 2:45 am

    On Wed, 13 Nov 2013 18:10:59 -0800, Rick Johnson wrote:

    On Wednesday, November 13, 2013 5:42:24 PM UTC-6, Rhodri James wrote:
    On Tue, 12 Nov 2013 02:06:09 -0000, Rick Johnson wrote:
    PyMyth: Global variables are evil... WRONG!
    That's not a PyMyth. It's a CompSciMyth, or to be more accurate a good
    general Software Engineering guideline regardless of language. Like
    all guidelines it can be broken, but people who break it should do so
    knowingly, aware that they have created potential problems for
    themselves.
    You speak as if using globals are inhabited by gremlins just wanting to
    get out and run a muck. There are no "inherent" problems in the global
    interface design except those that programmer inserts himself.

    Real global variable interfacing is no different than python object
    member interfacing, or module interfacing, except that the latter two
    are encapsulated by inside a namespace, and the former (historically)
    are unprotected and available everywhere; hence the name "global" :-)

    A fully-auto machine gun with a hair-trigger and no safety is no
    different from a single-barrel shotgun with a safety and a trigger lock!
    You can blow your foot off with both!


    Yes, but in the first case you can do it by accident, while with the
    second you have to work hard to blow your foot off.



    So that renders this whole argument of "global gremlins" as FUD. The
    gremlins don't exist until the programmer creates them.

    Wait... are you saying that software bugs only occur because the coder
    writes buggy software? I thought bugs came into existence via spontaneous
    generation, like viruses, bacteria, pigeons and Marine Corps sergeants.



    And i also want to point out the hypocrisy of Python's design. Python
    DOES have globals

    Is that why it has a global keyword and a globals() function? Thanks for
    the information, I never would have worked that out without your keen
    insight.




    --
    Steven
  • Rick Johnson at Nov 14, 2013 at 3:45 am

    On Wednesday, November 13, 2013 8:45:16 PM UTC-6, Steven D'Aprano wrote:
    A fully-auto machine gun with a hair-trigger and no
    safety is no different from a single-barrel shotgun with
    a safety and a trigger lock! You can blow your foot off
    with both!

    Yes. But in the case of the shotgun you'd have to find the
    key, unlock the trigger, unset the safety, and aim REALLY
    well... because your only getting off one shot, and if you
    miss or only wound me, i've got that full auto machine gun
    with hair trigger and no safety -- i won't need to live very
    long to return the favor. >:)

    Yes, but in the first case you can do it by
    accident, while with the second you have to work hard to
    blow your foot off.

    Uh huh.


    And why do i have the sneaking suspicion that the BIG SCARY
    ASSAULT WEAPON is referring to my argument and the "old
    shot-gun that Grandpa has in the closet under lock and key"
    is your argument.


    But more importantly, why is all this straw scattered across
    the floor?


    Very strange.


    Very strange indeed.
  • Rick Johnson at Nov 14, 2013 at 4:01 am
    And what's this?


         *picks up hat*


    Where did this hat come from???


    Spectator interrupts: Maybe Steven threw his hat in?


    No, no.


    Can't be.


    Steven would not wear something this old.


    I mean, it looks like something a farmer would put on a
    scarecrow or something???


         *scratched head*


    OH MY GAWD!


         *throws hat on floor*


    That hat has crow poop on it!


    Could someone PLEASE get a janitor in here to clean this
    mess up!


    For Christs sakes we're trying to have a technical
    discussion here and some prankster goes and tosses a
    straw grenade right in the middle of it!


    How rude!
  • Steven D'Aprano at Nov 14, 2013 at 5:50 am

    On Wed, 13 Nov 2013 19:45:42 -0800, Rick Johnson wrote:

    On Wednesday, November 13, 2013 8:45:16 PM UTC-6, Steven D'Aprano wrote:
    A fully-auto machine gun with a hair-trigger and no
    safety is no different from a single-barrel shotgun with a safety and
    a trigger lock! You can blow your foot off with both!
    Yes. But in the case of the shotgun you'd have to find the key, unlock
    the trigger, unset the safety, and aim REALLY well... because your only
    getting off one shot, and if you miss or only wound me, i've got that
    full auto machine gun with hair trigger and no safety -- i won't need to
    live very long to return the favor. >:)

    I think you're missing the point that we're talking about the coder
    shooting themselves in the foot, not Gunfight At The OK Corral. There's
    no "favour" to return.



    Yes, but in the first case you can do it by accident, while with the
    second you have to work hard to blow your foot off.
    Uh huh.

    And why do i have the sneaking suspicion that the BIG SCARY ASSAULT
    WEAPON is referring to my argument and the "old shot-gun that Grandpa
    has in the closet under lock and key" is your argument.

    That's the most insightful observation you've made in this thread so far.


    Yes, the point is that process-wide global variables are demonstrated by
    50+ years of programming experience to be best avoided (in general --
    there are caveats and exceptions of course). We're talking about probably
    millions of person-hours of experience leading to the conclusion that
    "globals are harmful".


    It isn't that global variables will leap out of the computer and attack
    you while you sleep, of course, but that in general *its too damn hard*
    for human programmers to write good, reliable, maintainable, correct
    (i.e. bug-free) code using process-wide global variables. Global
    variables are the spaghetti code of namespacing -- everything is mixed up
    together in one big tangled mess.


    The more global variables you have, the worse the tangle. One or two is
    not too bad. With good conventions for encapsulation to limit the amount
    of tangled, coupled code (e.g. naming conventions, or limiting globals to
    a single module at a time by default) the amount of harm can be reduced
    to manageable levels.


    Global variables increases coupling between distant parts of the code. I
    remember a nasty little bug in Windows where removing IE stopped copy-and-
    paste from working everywhere. That's a sign of excess coupling between
    code -- there's no logical reason why removing a web browser should cause
    copying text in Notepad to fail. We want to avoid unnecessary coupling:
    opening your fridge door shouldn't flush the toilet.


    Since global variables increase coupling, and coupling is often harmful,
    one way to avoid unnecessary coupling is to avoid unnecessary global
    variables. Think of them as leaches. Even today, there are good uses for
    medical leaches:


    http://en.wikipedia.org/wiki/Hirudo_medicinalis




    One or two leaches is hardly noticeable. Ten or twenty starts being a bit
    of a problem. A few dozen and you'll certainly notice, and if you're
    covered in multiple hundreds of them, you're at risk of dying from blood
    loss, never mind the risk of infection.




    --
    Steven
  • Rick Johnson at Nov 14, 2013 at 5:26 pm

    On Wednesday, November 13, 2013 11:50:40 PM UTC-6, Steven D'Aprano wrote:
    On Wed, 13 Nov 2013 19:45:42 -0800, Rick Johnson wrote:
    On Wednesday, November 13, 2013 8:45:16 PM UTC-6, Steven D'Aprano wrote:
    A fully-auto machine gun with a hair-trigger and no
    safety is no different from a single-barrel shotgun with a safety and
    a trigger lock! You can blow your foot off with both!
    Yes. But in the case of the shotgun you'd have to find the key, unlock
    the trigger, unset the safety, and aim REALLY well... because your only
    getting off one shot, and if you miss or only wound me, i've got that
    full auto machine gun with hair trigger and no safety -- i won't need to
    live very long to return the favor. >:)
    I think you're missing the point that we're talking about the coder
    shooting themselves in the foot, not Gunfight At The OK Corral. There's
    no "favour" to return.

    And you missed the point that i took your straw-man and
    converted him into satire. You owe me gratitude for
    *politely* ignoring your repeated logical fallacies.

    Yes, the point is that process-wide global variables are
    demonstrated by 50+ years of programming experience to be
    best avoided (in general -- there are caveats and
    exceptions of course). We're talking about probably
    millions of person-hours of experience leading to the
    conclusion that "globals are harmful".

    But yet Python has globals, you just have to *import* them.
    But that design is flawed

    It isn't that global variables will leap out of the
    computer and attack you while you sleep,

    Funny, that sounds like my argument from earlier. Something
    about "gremlins".

    of course, but that in general *its too damn hard* for
    human programmers to write good, reliable, maintainable,
    correct (i.e. bug-free) code using process-wide global
    variables.

    Complete FUD. Maybe for you. Not for me.

    Global variables are the spaghetti code of namespacing --
    everything is mixed up together in one big tangled mess.

    It's a tangled mess if you design it to be a tangled mess.

    The more global variables you have, the worse the tangle.

    Complete illogic.


    What if all the globals are only accessed
    and never mutated? You could have a million globals that never
    change (of course they'd technically be constants) and never
    suffer a single error from globals EVEN IF your an incompetent
    software designer.

    One or two is not too bad. With good conventions for
    encapsulation to limit the amount of tangled, coupled code
    (e.g. naming conventions, or limiting globals to a single
    module at a time by default) the amount of harm can be
    reduced to manageable levels.
    SO now your agreeing that globals are not evil again. I
    positied an anaology in a passed thred that went something
    like this:

    ManufacurerA claims his car is the safest on the road.


    ManfacturerB drives ManfacturerA's car into a ditch and then
    claims ManfacturerA is a liar.


    Result: Who is wrong?

    Global variables increases coupling between distant parts
    of the code. I remember a nasty little bug in Windows
    where removing IE stopped copy-and- paste from working
    everywhere. That's a sign of excess coupling between code
    -- there's no logical reason why removing a web browser
    should cause copying text in Notepad to fail.

    Do you have link describing this bug? I am not aware of such
    bug ,but uh, i would not at all be surprised that windows
    could break from removing that gawd awful IE.


    Come to think of it, i'll bet it's not even a bug at all,
    but a feature to prevent "wise users" from removing IE,
    thereby maintaining IE's footprint in the wild.


    Steven, this sounds more like Fascism than "clumsy use of
    globals" to me.


    But even IF globals are to blame, by removing IE, you have
    removed a large chunk of code from a code base that was not
    designed for modularity. (We could argue whether or not
    windows should allow removal of IE, but ultimately that is
    M$ decision)


    No developer could possibly forecast every possible "bad
    thing" a user might decide to do. Especially when we're
    talking about ripping components of the software out
    completely.


    Do i think IE should be a removal component? HECK YEAH, and
    i would have designed it that way. But IS is not my baby, it
    belongs to Mr. Gates, and he designs his software any way he
    damn well pleases, and you and i can choose not to use it.


    Image if someone downloaded Python and just started ripping
    out source files willy-nilly because they did not like them
    for whatever reason. Then, they came to this list and start
    bitching because Python was blowing chunks. And don't give
    examples of things that can be ripped out without breaking
    Python, because that is germane either.


    How would you respond to such complaints?


    Hmm...never thought you'd be agree with Mr. Gates did ya?

    We want to avoid unnecessary coupling: opening your fridge
    door shouldn't flush the toilet.

    *KAH-BOOM* (Straw-bomb expodes)(AGAIN!)

    Since global variables increase coupling, and coupling is
    often harmful, one way to avoid unnecessary coupling is to
    avoid unnecessary global variables.

    Nice! Your attempts to posit that "harmful coupling" is the
    almost unavoidable outcome of "globals" is not fooling me.
    Here's another way to phrase:


         Since transportation increases chances of death or
         injury from accidents, and death or injury is often
         harmful, one way to to avoid unnecessary death or injury
         is to avoid transportation.


    There are two logical ways to react to such grim reality:


         We could become consumed with fear and destroy all motor
         vehicles, bicycles, skateboards, etc... and instead
         adopt the locomotion of our forefathers by utilizing our
         feet. or,


         We reduce the risks to almost nothing by designing and
         implementing globals via a logical and consistent
         interface. Then, to be sure, we test religiously
         (psst:we should be doing this anyway!!!)


    But what we don't want to do is lull ourselves into a false
    sense of security by "hiding" globals behind a pseudo
    interface and thinking we have solved the problem of
    globals.


    And this is what Python modules are doing!


    No, you've solved nothing. All you've done is to
    stick you head in the sand.


    ============================================================
      It's my code, my problem, not yours!
    ============================================================


    Yes, you are correct.


    If you want to go on using globals in a dangerous way, or
    using module attributes and believing falsely they're not
    global, then by all means go on. HOWEVER, don't infect the
    world with your sloppy architecture. KEEP YOU CODE TO
    YOURSELF!


    But that's not the case is it, NO, many of you are infecting
    Python's code base with horrible code.


    Python's warts are *really* exposed when Python is embedded
    as a scripting language. Since multiple scripts from
    multiple authors will be running under the same process, any
    one of them can bring the whole house of cards crashing
    down. And with Python's current design, that possibility is
    more likely.


    It's sad, because Python is a great choice for scripting,
    but the major design flaws are self defeating. Even
    the best syntax ever created cannot make up for such
    illogical inconsistencies at the core.

    Think of them as leaches. [snip remaining straw-bombs]
  • Joel Goldstick at Nov 14, 2013 at 5:37 pm

    On Thu, Nov 14, 2013 at 12:26 PM, Rick Johnson wrote:
    On Wednesday, November 13, 2013 11:50:40 PM UTC-6, Steven D'Aprano wrote:
    On Wed, 13 Nov 2013 19:45:42 -0800, Rick Johnson wrote:
    On Wednesday, November 13, 2013 8:45:16 PM UTC-6, Steven D'Aprano wrote:
    A fully-auto machine gun with a hair-trigger and no
    safety is no different from a single-barrel shotgun with a safety and
    a trigger lock! You can blow your foot off with both!
    Yes. But in the case of the shotgun you'd have to find the key, unlock
    the trigger, unset the safety, and aim REALLY well... because your only
    getting off one shot, and if you miss or only wound me, i've got that
    full auto machine gun with hair trigger and no safety -- i won't need to
    live very long to return the favor. >:)
    I think you're missing the point that we're talking about the coder
    shooting themselves in the foot, not Gunfight At The OK Corral. There's
    no "favour" to return.
    And you missed the point that i took your straw-man and
    converted him into satire. You owe me gratitude for
    *politely* ignoring your repeated logical fallacies.
    Yes, the point is that process-wide global variables are
    demonstrated by 50+ years of programming experience to be
    best avoided (in general -- there are caveats and
    exceptions of course). We're talking about probably
    millions of person-hours of experience leading to the
    conclusion that "globals are harmful".
    But yet Python has globals, you just have to *import* them.
    But that design is flawed
    It isn't that global variables will leap out of the
    computer and attack you while you sleep,
    Funny, that sounds like my argument from earlier. Something
    about "gremlins".
    of course, but that in general *its too damn hard* for
    human programmers to write good, reliable, maintainable,
    correct (i.e. bug-free) code using process-wide global
    variables.
    Complete FUD. Maybe for you. Not for me.
    Global variables are the spaghetti code of namespacing --
    everything is mixed up together in one big tangled mess.
    It's a tangled mess if you design it to be a tangled mess.
    The more global variables you have, the worse the tangle.
    Complete illogic.

    What if all the globals are only accessed
    and never mutated? You could have a million globals that never
    change (of course they'd technically be constants) and never
    suffer a single error from globals EVEN IF your an incompetent
    software designer.
    One or two is not too bad. With good conventions for
    encapsulation to limit the amount of tangled, coupled code
    (e.g. naming conventions, or limiting globals to a single
    module at a time by default) the amount of harm can be
    reduced to manageable levels.
    SO now your agreeing that globals are not evil again. I
    positied an anaology in a passed thred that went something
    like this:
    ManufacurerA claims his car is the safest on the road.

    ManfacturerB drives ManfacturerA's car into a ditch and then
    claims ManfacturerA is a liar.

    Result: Who is wrong?
    Global variables increases coupling between distant parts
    of the code. I remember a nasty little bug in Windows
    where removing IE stopped copy-and- paste from working
    everywhere. That's a sign of excess coupling between code
    -- there's no logical reason why removing a web browser
    should cause copying text in Notepad to fail.
    Do you have link describing this bug? I am not aware of such
    bug ,but uh, i would not at all be surprised that windows
    could break from removing that gawd awful IE.

    Come to think of it, i'll bet it's not even a bug at all,
    but a feature to prevent "wise users" from removing IE,
    thereby maintaining IE's footprint in the wild.

    Steven, this sounds more like Fascism than "clumsy use of
    globals" to me.

    But even IF globals are to blame, by removing IE, you have
    removed a large chunk of code from a code base that was not
    designed for modularity. (We could argue whether or not
    windows should allow removal of IE, but ultimately that is
    M$ decision)

    No developer could possibly forecast every possible "bad
    thing" a user might decide to do. Especially when we're
    talking about ripping components of the software out
    completely.

    Do i think IE should be a removal component? HECK YEAH, and
    i would have designed it that way. But IS is not my baby, it
    belongs to Mr. Gates, and he designs his software any way he
    damn well pleases, and you and i can choose not to use it.

    Image if someone downloaded Python and just started ripping
    out source files willy-nilly because they did not like them
    for whatever reason. Then, they came to this list and start
    bitching because Python was blowing chunks. And don't give
    examples of things that can be ripped out without breaking
    Python, because that is germane either.

    How would you respond to such complaints?

    Hmm...never thought you'd be agree with Mr. Gates did ya?
    We want to avoid unnecessary coupling: opening your fridge
    door shouldn't flush the toilet.
    *KAH-BOOM* (Straw-bomb expodes)(AGAIN!)
    Since global variables increase coupling, and coupling is
    often harmful, one way to avoid unnecessary coupling is to
    avoid unnecessary global variables.
    Nice! Your attempts to posit that "harmful coupling" is the
    almost unavoidable outcome of "globals" is not fooling me.
    Here's another way to phrase:

    Since transportation increases chances of death or
    injury from accidents, and death or injury is often
    harmful, one way to to avoid unnecessary death or injury
    is to avoid transportation.

    There are two logical ways to react to such grim reality:

    We could become consumed with fear and destroy all motor
    vehicles, bicycles, skateboards, etc... and instead
    adopt the locomotion of our forefathers by utilizing our
    feet. or,

    We reduce the risks to almost nothing by designing and
    implementing globals via a logical and consistent
    interface. Then, to be sure, we test religiously
    (psst:we should be doing this anyway!!!)

    But what we don't want to do is lull ourselves into a false
    sense of security by "hiding" globals behind a pseudo
    interface and thinking we have solved the problem of
    globals.

    And this is what Python modules are doing!

    No, you've solved nothing. All you've done is to
    stick you head in the sand.

    ============================================================
    It's my code, my problem, not yours!
    ============================================================

    Yes, you are correct.

    If you want to go on using globals in a dangerous way, or
    using module attributes and believing falsely they're not
    global, then by all means go on. HOWEVER, don't infect the
    world with your sloppy architecture. KEEP YOU CODE TO
    YOURSELF!

    But that's not the case is it, NO, many of you are infecting
    Python's code base with horrible code.

    Python's warts are *really* exposed when Python is embedded
    as a scripting language. Since multiple scripts from
    multiple authors will be running under the same process, any
    one of them can bring the whole house of cards crashing
    down. And with Python's current design, that possibility is
    more likely.

    It's sad, because Python is a great choice for scripting,
    but the major design flaws are self defeating. Even
    the best syntax ever created cannot make up for such
    illogical inconsistencies at the core.
    Think of them as leaches. [snip remaining straw-bombs]
    --
    https://mail.python.org/mailman/listinfo/python-list

    I've been following along this thread a little bit. From what I get
    out of it that the OP thinks only lousy coders can't write good code
    with globals. If you are skilled (as he claims) they are useful. The
    con argument says that over 50 years of learning how to make better
    more productive computer languages, globals end up causing certain
    problems.


    So, beyond that, what is the point of the thread? Is it about python?
      Just barely I guess


    --
    Joel Goldstick
    http://joelgoldstick.com
  • Ethan Furman at Nov 14, 2013 at 5:56 pm

    On 11/14/2013 09:37 AM, Joel Goldstick wrote:
    So, beyond that, what is the point of the thread?

    You haven't met Ranting Rick yet? He's a troll's troll, outdone only by one other whose name I don't remember.


    His posts are, amazingly enough, rants. Usually about his (mis)perceptions of the failures of:


        - Python
        - The Python Leaders
        - Good Coding Practices
        - Everyone but himself (and the "Silent Majority" he represents)


    He has been on vacation for a few months, but, alas, he is back. Interestingly, even though he is still in my kill file
    I could tell the thread was his just from the subject title.


    --
    ~Ethan~
  • Joel Goldstick at Nov 14, 2013 at 6:43 pm

    On Thu, Nov 14, 2013 at 12:56 PM, Ethan Furman wrote:
    On 11/14/2013 09:37 AM, Joel Goldstick wrote:


    So, beyond that, what is the point of the thread?

    You haven't met Ranting Rick yet? He's a troll's troll, outdone only by one
    other whose name I don't remember.

    His posts are, amazingly enough, rants. Usually about his (mis)perceptions
    of the failures of:

    - Python
    - The Python Leaders
    - Good Coding Practices
    - Everyone but himself (and the "Silent Majority" he represents)

    He has been on vacation for a few months, but, alas, he is back.
    Interestingly, even though he is still in my kill file I could tell the
    thread was his just from the subject title.

    --
    ~Ethan~
    --
    https://mail.python.org/mailman/listinfo/python-list

    Ah, thanks. A tag team .. oh my!


    --
    Joel Goldstick
    http://joelgoldstick.com
  • Mark Lawrence at Nov 14, 2013 at 7:04 pm

    On 14/11/2013 17:56, Ethan Furman wrote:
    On 11/14/2013 09:37 AM, Joel Goldstick wrote:

    So, beyond that, what is the point of the thread?
    You haven't met Ranting Rick yet? He's a troll's troll, outdone only by
    one other whose name I don't remember.

    His posts are, amazingly enough, rants. Usually about his
    (mis)perceptions of the failures of:

    - Python
    - The Python Leaders
    - Good Coding Practices
    - Everyone but himself (and the "Silent Majority" he represents)

    He has been on vacation for a few months, but, alas, he is back.
    Interestingly, even though he is still in my kill file I could tell the
    thread was his just from the subject title.

    --
    ~Ethan~

    But he's not 100% troll as he has published some useful stuff on
    IDLE/tkinter, that's why he's only on the subs bench for my Trolls Dream
    Team. No guesses who the captain is now :)


    --
    Python is the second best programming language in the world.
    But the best has yet to be invented. Christian Tismer


    Mark Lawrence
  • Alister at Nov 14, 2013 at 8:12 pm

    On Thu, 14 Nov 2013 09:56:04 -0800, Ethan Furman wrote:

    On 11/14/2013 09:37 AM, Joel Goldstick wrote:

    So, beyond that, what is the point of the thread?
    You haven't met Ranting Rick yet? He's a troll's troll, outdone only by
    one other whose name I don't remember.

    His posts are, amazingly enough, rants. Usually about his
    (mis)perceptions of the failures of:

    - Python - The Python Leaders - Good Coding Practices - Everyone but
    himself (and the "Silent Majority" he represents)

    He has been on vacation for a few months, but, alas, he is back.
    Interestingly, even though he is still in my kill file I could tell the
    thread was his just from the subject title.

    I don't think there is any comparison.
    Ricks trolls do at least promote intelligent discussion & cause the
    reader to re-asses preconceptions if only to confirm them.


    Ricks non trolling posts do give him enough credibility to avoid
    dismissing his ideas out of hand










    --
    Go away! Stop bothering me with all your "compute this ... compute that"!
    I'm taking a VAX-NAP.


    logout
  • Chris Angelico at Nov 14, 2013 at 10:43 pm

    On Fri, Nov 15, 2013 at 7:12 AM, Alister wrote:
    Ricks non trolling posts do give him enough credibility to avoid
    dismissing his ideas out of hand

    When he's talking about Tkinter, he knows his stuff, and is orders of
    magnitude more helpful than I would be (as I don't know Tkinter). When
    he's talking about warts in Python, he sometimes knows what he's
    talking about, often ignores facts, and generally is more stirring the
    pot than actually being productive. But hey, they can still be fun
    threads.


    Now, I'm just waiting for the thread in which Nikos has problems with
    Tkinter not working with Greek characters as of Python 3.3, and a
    singularity is formed that results in the destruction of the known
    universe...


    ChrisA
  • Steven D'Aprano at Nov 15, 2013 at 8:19 am

    On Thu, 14 Nov 2013 09:26:18 -0800, Rick Johnson wrote:


    On Wednesday, November 13, 2013 11:50:40 PM UTC-6, Steven D'Aprano
    wrote:
    [...]
    of course, but that in general *its too damn hard* for human
    programmers to write good, reliable, maintainable, correct (i.e.
    bug-free) code using process-wide global variables.
    Complete FUD. Maybe for you. Not for me.

    I wasn't taking about genius programmers like you Rick, that would be
    silly. I'm talking about mere mortals like the rest of us.



    Global variables are the spaghetti code of namespacing -- everything is
    mixed up together in one big tangled mess.
    It's a tangled mess if you design it to be a tangled mess.

    Nobody sets out to *design* a tangled mess. What normally happens is that
    a tangled mess is the result of *lack of design*.



    The more global variables you have, the worse the tangle.
    Complete illogic.

    What if all the globals are only accessed and never mutated?

    Then they aren't global VARIABLES. You'll note that I was very careful to
    refer to "variables".


    Read-only global constants don't increase coupling to anywhere near the
    same degree as writable global variables. As such, they're far less
    harmful.


    Of course, there is still some degree of coupling -- suppose one chunk of
    code wants a global constant X# and another chunk of code wants a
    global constant XB? But such issues are generally easy to spot and easy
    to fix.



    One or two is not too bad. With good conventions for encapsulation to
    limit the amount of tangled, coupled code (e.g. naming conventions, or
    limiting globals to a single module at a time by default) the amount of
    harm can be reduced to manageable levels.
    SO now your agreeing that globals are not evil again.

    In this thread, I have never called global variables "evil". I have
    called them *harmful*, and tried to make it clear that harm is not a
    dichotomy "zero harm" versus "infinite harm", but a matter of degree. I
    stand by that.



    Global variables increases coupling between distant parts of the code.
    I remember a nasty little bug in Windows where removing IE stopped
    copy-and- paste from working everywhere. That's a sign of excess
    coupling between code -- there's no logical reason why removing a web
    browser should cause copying text in Notepad to fail.
    Do you have link describing this bug? I am not aware of such bug ,but
    uh, i would not at all be surprised that windows could break from
    removing that gawd awful IE.

    Come to think of it, i'll bet it's not even a bug at all, but a feature
    to prevent "wise users" from removing IE, thereby maintaining IE's
    footprint in the wild.

    Heh.


    Sorry, I can't find the link. It was well over five years ago, probably
    more like ten. But whether deliberate or accidental, that's the sort of
    thing I mean when I talk about excessive coupling. Note that coupling in
    and of itself is not harmful -- for example, you want the brake pedal of
    your car to be coupled to the brakes. Excess and inappropriate coupling
    is harmful: pressing the brake pedal shouldn't turn off the headlights,
    nor should a blown brake light stop the brakes from working. Hence we try
    to minimize coupling to only those areas that actually need them.


    With physical devices, that's often -- not always -- trivial. The
    constraints of physical matter makes it natural to keep things loosely
    coupled. When you're building a car, the hard part is getting the
    coupling that you actually do want, not avoiding coupling you don't.
    Physical devices are, as a general rule, inherently and naturally
    encapsulated: the brake pedal is physically uncoupled from the brakes
    unless you literally connect them with steel cables and wires. Your
    fridge isn't connected to anything except the power supply, so it
    physically can't flush the toilet. Since the toilet and fridge are made
    in different factories and installed by different people, there's no
    motivation to couple them. Even if some bright spark decided that since
    opening the fridge door turns on the fridge light, and pressing the
    toilet button opens the cistern value, the two operations are related and
    therefore "Don't Repeat Yourself" applies and there should be a single
    mechanism to do both, it is impractical to build such a system. (And
    thank goodness. But just wait until we have internet-enabled fridges and
    toilets...)


    But with software, coupling is *easy*. By default, code in a single
    process is completely coupled. Think of a chunk of machine code running
    in a single piece of memory. We have to build in our own conventions for
    decoupling code: subroutines, local variables, objects, modular code, and
    so forth. Physical objects are inherently decoupled. Code is inherently
    coupled, and we need conventions to decouple it. One of those conventions
    is to prefer local variables to global variables, and another is to limit
    the scope of global variables to per module rather than process-wide.






    --
    Steven
  • Tim Daneliuk at Nov 15, 2013 at 3:26 pm

    On 11/15/2013 02:19 AM, Steven D'Aprano wrote:
    Nobody sets out to*design* a tangled mess. What normally happens is that
    a tangled mess is the result of*lack of design*.

    This has been an interesting thread - to me anyway - but this bit
    above caught my eye. People write programs for lots of reasons -
    personal, academic, scientific, and commercial - but I actually
    don't thing the resultant messes are caused by a "lack of
    design" most of the time. In my experience they're caused by only two things:


    1) A lack of skill by inexperienced programmers who've been
         given more to do than they're yet ready to do and whose
         senior colleagues are not mentoring them (or such mentoring
         is being rejected because of ego and/or politics).


    2) An evolving set of requirements.


    #2 is particularly prevalent in commercial environments. Modern
    business is forced to respond to changing commercial conditions
    in nearly realtime these days. The pace of required innovation is
    fast that - all too often - no one actually knows what the "requirements"
    are during the design phase. Requirements get *discovered* during the
    coding phase. This is not a moral failing or lack of discipline, it's
    the simple reality that what you thought you needed to deliver changed
    in the intervening 6 months of coding because the business changed.




    ----------------------------------------------------------------------------
    Tim Daneliuk tundra at tundraware.com
    PGP Key: http://www.tundraware.com/PGP/
  • Chris Angelico at Nov 15, 2013 at 3:42 pm

    On Sat, Nov 16, 2013 at 2:26 AM, Tim Daneliuk wrote:
    On 11/15/2013 02:19 AM, Steven D'Aprano wrote:
    Nobody sets out to*design* a tangled mess. What normally happens is that
    a tangled mess is the result of*lack of design*.
    This has been an interesting thread - to me anyway - but this bit
    above caught my eye. People write programs for lots of reasons -
    personal, academic, scientific, and commercial - but I actually
    don't thing the resultant messes are caused by a "lack of
    design" most of the time. In my experience they're caused by only two
    things:

    2) An evolving set of requirements.

    This can be an explanation for a lack of design, but it's no less a
    lack. Sometimes, something just grows organically... from a nucleus of
    good design, but undesigned growth. Maybe it's time it got redesigned;
    or maybe redesigning would take too much effort and it's just not
    worth spending that time on something that's going to be phased out by
    the next shiny thing in a couple of years anyway. Doesn't change the
    fact that the current state is not the result of design, but of
    disorganized feature creep. That's not necessarily a terrible thing,
    but Steven's point still stands: such lack of design often results in
    a tangled mess, and a tangled mess can often be blamed on lack of
    design.


    ChrisA
  • Tim Daneliuk at Nov 15, 2013 at 11:33 pm

    On 11/15/2013 09:42 AM, Chris Angelico wrote:
    On Sat, Nov 16, 2013 at 2:26 AM, Tim Daneliuk wrote:
    On 11/15/2013 02:19 AM, Steven D'Aprano wrote:
    Nobody sets out to*design* a tangled mess. What normally happens is that
    a tangled mess is the result of*lack of design*.
    This has been an interesting thread - to me anyway - but this bit
    above caught my eye. People write programs for lots of reasons -
    personal, academic, scientific, and commercial - but I actually
    don't thing the resultant messes are caused by a "lack of
    design" most of the time. In my experience they're caused by only two
    things:

    2) An evolving set of requirements.
    This can be an explanation for a lack of design, but it's no less a
    lack. Sometimes, something just grows organically... from a nucleus of
    good design, but undesigned growth. Maybe it's time it got redesigned;
    or maybe redesigning would take too much effort and it's just not
    worth spending that time on something that's going to be phased out by
    the next shiny thing in a couple of years anyway. Doesn't change the
    fact that the current state is not the result of design, but of
    disorganized feature creep. That's not necessarily a terrible thing,
    but Steven's point still stands: such lack of design often results in
    a tangled mess, and a tangled mess can often be blamed on lack of
    design.

    ChrisA

    A fair point. Perhaps a better way to say this would be "Code that
    is a tangled mess is often so because good design was not possible
    during its creation."


    The problem, of course, is that in almost all circumstances there is usually
    not a lot of economic benefit to redesign and restructure the code
    once you *do* know the requirements. Other projects compete for attention
    and fixing old, ugly stuff rarely gets much attention. This is particularly
    true insofar as most organizations do a lousy job of tracking what it
    is really costing them to operate that kind of code. If they did, cleaning
    things up would become a much bigger priority.


    Oh, and inevitably, the person that wrote the code without stable requirements
    and without being given time to go back, refactor, cleanup, and restructure the
    code ... gets blamed by the people that have to run and maintain it.


    <Old Coders Love To Tell Stories Warning>


    Years ago I worked for a company that did embedded banking software that
    ran on high speed check readers. It was an "application" that had been
    undergoing constant feature creep and change during about an 18 month period
    because the woman in marketing running the program get getting
    Bright New Ideas (tm) to peddle.


    The programmer - frustrated by this - began adding increasingly direct,
    personal, and biological comments about said marketing person in the
    comments of his assembler code. Anyway, the new feature requests finally
    stopped, and she came in one day to briskly inform us that the code
    had been sold to one of our customers and she'd need a tape by end of
    week. The guy who'd been writing all this turned sheet white and scrambled
    over the next few days to expunge all his nasty comments from thousands
    of lines of assembler. It was most entertaining to watch ...


    --
    ----------------------------------------------------------------------------
    Tim Daneliuk tundra at tundraware.com
    PGP Key: http://www.tundraware.com/PGP/
  • Rick Johnson at Nov 16, 2013 at 4:01 am

    On Friday, November 15, 2013 2:19:01 AM UTC-6, Steven D'Aprano wrote:


    But with software, coupling is *easy*. By default, code in
    a single process is completely coupled. Think of a chunk
    of machine code running in a single piece of memory. We
    have to build in our own conventions for decoupling code:
    subroutines, local variables, objects, modular code, and
    so forth. Physical objects are inherently decoupled. Code
    is inherently coupled, and we need conventions to decouple
    it. One of those conventions is to prefer local variables
    to global variables, and another is to limit the scope of
    global variables to per module rather than process-wide.

    You're thoughts on "coupling" and "decoupling"
    of design architecture is correct, but you only argue for
    your side :-). Allow me to now argue for my side now.


    And i want to leave the "safe" world of general analogies
    and enter the dark esoteric word of flawed software design.


    And since people only want to give me credit when i talk
    about Tkinter, well then, what better example of bad design
    is there than Tkinter? Hmm, well there's IDLE but that will
    have to wait for another thread.


    Let's see... Tkinter's design today is a single module
    containing a staggering:


         155,626 chars


         3,733 lines


         30 classes


         16 functions


         4 "puesdo-constants" (Python does not support true
         constants!)


         10 "module level" variables (3 of which are mutated from
         nested scopes within the module itself)


         Unwise use of a global import for the types module, even
         though only a few names are used -- AND there are
         better ways to test type nowadays!


         Unwisely auto-imports 82 Tkinter constants.


    Only OpenGL is more promiscuous than Tkinter!


    But let's stay on subject shall we!


    ============================================================
       The Road To Recovery:
    ============================================================


    The very first thing a wise programmer would do is create a
    package called "tkinter". Then, he would export all class
    source code to individual sub-modules -- each module being
    the class name in lowercase.


         AND VOILA!


    Even after only a simple half hour of restructuring, the
    code is starting to become maintainable -- IMAGINE THAT!




         BUT DON'T GET YOUR ASTROGLIDE OUT YET FELLA!


         WE'VE GOT MORE WORK TO DO!


    Just as the programmer thought "all was well" in "toon
    town", he quickly realizes that since Python has no
    intelligent global variable access, and his sub-modules need
    to share data with the main tkinter module (and vise versa),
    he will be forced to write:


         from tkinter import var1, var2, ..., varN


         IN EVERY DAMN SUBMODULE that needs to access or
         mutate one of the shared variables or shared
         functions.


    Can anyone tell me why sharing globals between sub-packages
    is really so bad that we have to import things over and
    over?


    And if so, would you like to offer a cleaner solution for
    the problem?


    And don't give me the messy import thing, because that's
    not elegant!


         WHY IS IT NOT ELEGANT RICK?


    Because when i see code that accesses a variable like this:


         var = value


    I have no way of knowing whether the mutation is happening
    to a local variable, a module level variable, or even a true
    global level variable (one which extends beyond the
    containing module).


    Sure, i could search the file looking for imports or
    global declarations, but why not use "self documenting
    paths" to global variables?


    The best solution is to create a global namespace. You could
    name it "G". So when i see a mutation like this:


         G.var = value:


    I will know that the mutation is happening to a REAL global
    variable. But, even that information is lacking. I need
    more... What i really want to see is this:


         G.tkinter.var = value


    Boom baby! Every thing i need to know is contained within
    that single line without "import everywhere".


        I am accessing a global variable
        I am accessing a global variable for the tkinter package
        The variable's name is "var"


    It's explicit, but it's not SO explicit that it becomes
    excessive, no. I would much rather type just a FEW more
    characters than scour source code looking for obscure clues
    like global declarations, imports, or whatever foolish
    design you can pull out of your arse!


         And what about the mysterious "run-time injected
         global", how the heck are you planning to handle
         that one with imports?


    I just want to access globals in an logical and consistent
    manner via a clean interface which will alleviate all the
    backtracking and detective work that causes us to lose focus
    on the main architecture of our software.


    Because,


         EXPLICIT IS BETTER THAN IMPLICIT.


    And,


         FOCUS IS BETTER THAN FRUSTRATION!


    Is that really too much to ask?


    Must i create a hack (C.py and G.py) for every missing or
    broken feature in this damn language?
  • Chris Angelico at Nov 16, 2013 at 4:14 am

    On Sat, Nov 16, 2013 at 3:01 PM, Rick Johnson wrote:
    Because when i see code that accesses a variable like this:

    var = value

    I have no way of knowing whether the mutation is happening
    to a local variable, a module level variable, or even a true
    global level variable (one which extends beyond the
    containing module).

    If it's in a function, and there's no global/nonlocal declaration,
    it's local. Otherwise, it's module level. It can't be process-level in
    Python, so you don't need to worry about that.


    It doesn't get much simpler than that without variable declarations
    (in which case it's "scan surrounding scopes till you find a
    declaration, that's it" - and it's arguable whether that's simpler or
    not). Really Rick, you're clutching at straws here.


    ChrisA
  • Chris Angelico at Nov 16, 2013 at 4:19 am

    On Sat, Nov 16, 2013 at 3:01 PM, Rick Johnson wrote:
    Let's see... Tkinter's design today is a single module
    containing a staggering:

    155,626 chars

    3,733 lines

    Also: I see nothing wrong with a single module having 3-4K lines in
    it. Hilfe, the Pike REPL/interactive interpreter, is about that long
    and it's not a problem to maintain. The Python decimal module (as
    opposed to CDecimal) is twice that, in the installation I have here to
    check. My primary C++ module from work was about 5K lines, I think -
    of that order, at least.


    Python modules don't need to be split up into tiny fragments.
    Flat is better than nested.


    ChrisA

Related Discussions

People

Translate

site design / logo © 2022 Grokbase