Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #104528 > unrolled thread
| Started by | Ian Kelly <ian.g.kelly@gmail.com> |
|---|---|
| First post | 2016-03-10 08:27 -0700 |
| Last post | 2016-03-14 15:55 -0700 |
| Articles | 9 on this page of 49 — 10 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-10 08:27 -0700
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-10 16:45 -0800
Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-11 08:47 -0700
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-11 18:39 -0800
Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-12 09:44 -0700
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-12 19:11 -0800
Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-13 21:11 +1100
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 10:32 -0700
Re: Encapsulation in Python Ian Kelly <ian.g.kelly@gmail.com> - 2016-03-14 15:09 -0600
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-14 21:23 +0000
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-14 22:07 +0000
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-14 22:20 +0000
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-14 22:40 +0000
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-14 23:19 +0000
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-14 23:56 +0000
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:12 +1100
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-15 00:54 +0000
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:58 +1100
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-15 01:22 +0000
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 13:02 +1100
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 00:28 +0000
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-15 01:10 +0000
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 12:23 +1100
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 04:41 +0000
Re: Encapsulation in Python rurpy@yahoo.com - 2016-03-14 17:17 -0700
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:25 +1100
Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:06 +1100
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 13:14 +1100
Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:40 +1100
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 21:08 -0700
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 00:47 +0000
Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:46 +1100
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-15 11:56 +1100
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 04:36 +0000
Re: Encapsulation in Python Steven D'Aprano <steve@pearwood.info> - 2016-03-15 13:01 +1100
Re: Encapsulation in Python Mark Lawrence <breamoreboy@yahoo.co.uk> - 2016-03-15 04:45 +0000
Re: Encapsulation in Python Christian Gollwitzer <auriocus@gmx.de> - 2016-03-15 22:02 +0100
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-16 00:39 +0000
Re: Encapsulation in Python BartC <bc@freeuk.com> - 2016-03-16 22:58 +0000
Re: Encapsulation in Python sohcahtoa82@gmail.com - 2016-03-14 11:11 -0700
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 23:09 -0700
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-11 18:56 -0800
Re: Encapsulation in Python Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-03-12 13:52 +1300
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-12 08:49 -0800
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-13 08:10 +1100
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-12 19:36 -0800
Re: Encapsulation in Python Chris Angelico <rosuav@gmail.com> - 2016-03-13 15:05 +1100
Re: Encapsulation in Python Gregory Ewing <greg.ewing@canterbury.ac.nz> - 2016-03-14 12:35 +1300
Re: Encapsulation in Python Rick Johnson <rantingrickjohnson@gmail.com> - 2016-03-14 15:55 -0700
Page 3 of 3 — ← Prev page 1 2 [3]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2016-03-14 23:09 -0700 |
| Message-ID | <bbafce4c-85b9-4d3f-9d3d-2e8e90318366@googlegroups.com> |
| In reply to | #104851 |
On Monday, March 14, 2016 at 1:12:14 PM UTC-5, sohca...@gmail.com wrote: [...a whole lot of my quotes, snipped for bandwidth...] @GROUP: I don't know what the heck happened in this thread, but everyone involved was having a nice respectful conversation about encapsulation, interfaces, and modules, and then BartC and Mark showed up, and the thread went off on a wild tangent. Whilst the participation of members and the CoC are important topics, i hope we put aside these petty issues, and get back to productive discussions soon. Thanks. > I don't think you'll find anyone that disagrees with you > here. > > If you're seeing a method "width", then whoever wrote that > method is a terrible programmer. Method names should > *always* contain some sort of verb. As you just said, > self-documenting names are the key to short learning > curves. > > IMO, if you intend an attribute to be read-only, then you > should use a getter, even in Python, Even though many of our fellow members would argue that this is overkill, your advice is good advice, and i strongly support this position. > and of course prefix the actual value with an underscore > to show it should not be accessed publicly. Agreed! > The only time you should see "someObject.width" is if > width is both readable and writable. Of course, Using > @property to add some logic to the setting/getting is > fine. Yes. More wonderful, and consistent, advice here. You sir, have restored my faith in humanity.
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2016-03-11 18:56 -0800 |
| Message-ID | <a98da235-4457-43d9-a4b8-0034767dafbb@googlegroups.com> |
| In reply to | #104622 |
On Friday, March 11, 2016 at 9:48:22 AM UTC-6, Ian wrote:
> On Thu, Mar 10, 2016 at 5:45 PM, Rick Johnson wrote:
> > Many times, i would have preferred to define my module space
> > across multiple files, multiple files that could share state
> > without resorting to the yoga-style "import contortions",
> > and/or the dreaded "circular import nightmares" that plague
> > our community today.
>
> Sounds to me like you're blaming Python for your own poor design.
> Possible solutions:
>
> 1) Don't do that. If your module is too big for one file, then it's
> likely poorly organized and doesn't all belong in one module anyway.
Apparently you've missed the many heated arguments between
Chris Angelico and myself concerning the size of source
files. I have *ALWAYS* taken the position that source files
should be kept as small as possible, but that position is
more relevant in Python, were modules are defined by a
single source file. I don't take the Java position that a
module can only contain one class, but i like to keep the
number of classes (IN MY SOURCE FILES) small.
At run-time, i don't care how large a "module namespace" may
be. Sometimes a module namespace will be small, with only a
few exposed symbols, but sometimes, a module namespace will
expose thousands of symbols. The size of a "run-time module"
is irrelevant in most languages, but here in Python, were
module namespace is defined by the contents of *ONE SINGLE
SOURCE FILE*, the whole ballgame is changed. If i need to
create a module that contains many exposed symbols in
Python, i'm forced to do one of the following:
(1) Write all my code in a single *GIGANTIC* file...
or
(2) Create one file that will be the "mother-ship module",
and N files that will be the "satellite modules", and from
inside the mother-ship, import all the symbols from all
the satellites. Ha, but in reality, it's not that simple,
because state does not "magically" travel between modules!
##########
# foo.py #
##########
FOO_SHARED_STATE = "foo"
import _fooSatilite1
_fooSatilite1.FOO_SHARED_STATE = FOO_SHARED_STATE
from _fooSatilite1 import *
import _fooSatilite2
_fooSatilite2.FOO_SHARED_STATE = FOO_SHARED_STATE
from _fooSatilite2 import *
print 'This is the mother-ship called foo'
...
####################
# _fooSatilite1.py #
####################
from _fooConstants import *
print 'This is foo-fighter1, reporting for duty'
print FOO_SHARED_STATE
...
####################
# _fooSatilite2.py #
####################
from _fooConstants import *
print 'This is foo-fighter2, reporting for duty'
print FOO_SHARED_STATE
...
But i find both to be absurd. Writing all code in a single
file might be fine for a toy module that contains a handful
of functions or classes or vars, but once we start creating
anything in the "professional size range", it will become
an "editing nightmare" of epic proportions!
But option two is no better, because once we cut and paste
portions of the code into satellite files, we lose the
ability to "easily share state". Then we're forced to start
"hacking at the weeds" with import contortions and monkey
patches, all the while, fearing the dreaded circular import.
NO, THIS IS INSANITY! WHAT WE NEED IS AN OPTION 3!
(3) Allow a programmer to define module space at will
##########
# foo.py #
##########
module foo
FOO_SHARED_STATE = "foo"
print 'This is the mother-ship called foo'
...
####################
# _fooSatilite1.py #
####################
module foo
print 'This is foo-fighter1, reporting for duty'
print FOO_SHARED_STATE # NO MP REQUIRED!
...
####################
# _fooSatilite2.py #
####################
module foo
print 'This is foo-fighter2, reporting for duty'
print FOO_SHARED_STATE # NO MP REQUIRED!
...
No need for import contortions, no need for monkey patching,
but most importantly, no need for professional programmers
to feel as though they are penchant little children, who
need their "module diapers" wrapped for them by mommy
Python, who, after popping one too many "mother's little
helpers", has a nasty habit of wrapping our diapers too damn
tight -- it's high time for these py-babies to go commando,
baby!
> 2) Clearly define which module is to be imported first. Then follow
> it. When module b is imported, it should import module a. When module
> a is imported, it *shouldn't* import module b until it's defined all
> of its own members first. If module a depends on anything from module
> b at import time, then refactor so it doesn't. This doesn't require
> "contortions".
That sounds simple in theory, but it breaks down quickly
when you create "professional sized programs"
> 3) Just put all your damn shared state in a class. There's nothing
> stopping you from spreading out your class method definitions over
> multiple files if you really want to, and it solves your import issue
> by allowing everything to be imported before you even begin to set up
> the shared state.
Your words tell me that you have not written anything substantial.
> And you're suggesting that public attributes and properties do not
> expose an interface? Rubbish.
No, what i'm suggesting, is that, from the POV of a dir
listing, they *ALL* look the same.
> I don't care how easy they are to *create*. Code is read much more
> often than it is written, and excessive boilerplate damages
> readability.
I understand the importance of readability, but is usability
of no concern to you? In fact, i would argue that, when
*ROCK SOLID* professional interfaces are combined with
proper documentation and strict adherence to style guides,
there is no need to read source code.
The only person who should be reading source, is a
maintenance programmer. And if the code was designed
properly, his job would be mostly just adding a feature here
or there, or repairing a small bug here or there -- any code
monkey can do that!
> > (2) Properties and attributes encourage vague naming
> > schemes. When i read code, i find the code more
> > comprehensible when the symbols give me clues as to what
> > is going on. So if i read code like: `re.groups`,
> > befuddlement sets in. What is "groups"? A function
> > object? An attribute? "getCapturingGroupCount" would be a
> > better name (but that's semantics)
>
> Actually, it would be wrong. Match.groups doesn't return a count.
Who said anything about match objects?
############################################################
# BEGIN INTERACTIVE SESSION
############################################################
py> import re
py> prog = re.compile(r'(Ian) (\w+)')
py> prog?
['findall', 'finditer', 'flags', 'groupindex', 'groups', 'match', 'pattern', 'scanner', 'search', 'split', 'sub', 'subn']
py> prog.groups
2
py> prog.groups?type
<type 'int'>
############################################################
# END INTERACTIVE SESSION
############################################################
Looks like an integer to me. (Well, i'll admit, first you'll
have to parse my mini-language syntax, but it's highly
intuitive -- more than a Python dir listing, i'll tell you
that much!)
> > In pure OOP, methods
> > are the only communication meduim, so we're more likely to
> > write "getBlah" and "setBlah", and use verbs for
> > procedural names -- these naming conventions are more
> > comprehensible to the user.
>
> Good names for methods are *descriptive* verb phrases. Good names for
> attributes and properties are *descriptive* nouns or noun phrases. Do
> you really believe that verbs are somehow inherently easier to
> understand?
When i see "get_width" or "set_width", i know that the first is
returning the width, and the second will set the width. And
anyone with an IQ over room temperature, can surmise that
set_width takes at least one argument.
However, when i see "width", how the hell am i supposed to
know if it is a read-only attribute, a property, or a method?
Must i read source code just to find this out? Sure, if the
author included a useful doc string, i could pull it up, but
to me, this is a giant waste of time. Self documenting names
are the *KEY* to short learning curves.
[toc] | [prev] | [next] | [standalone]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2016-03-12 13:52 +1300 |
| Message-ID | <dkh7i8Frq0gU1@mid.individual.net> |
| In reply to | #104568 |
Rick Johnson wrote: > I have witnessed the mayhem that occurs when a language does > not mandate module encapsulation (Ruby, i'm looking directly > at you!!!!), and while i agree with the Python designers > that modules must *ALWAYS* be mandatory, i am not convinced > that module space should be so strictly confined to source > files. Well, I am. When looking at someone else's code, it's very useful to be able to take a name used in one source file and easily find the file where it's defined. That's very easy to do in Python, and very hard to do in languages that don't relate namespaces and source files. The experiences I base this on aren't confined to Python. This is one of the very few things that I think Java got right, and some of the other JVM-based languages -- such as Scala -- got wrong. -- Greg
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2016-03-12 08:49 -0800 |
| Message-ID | <a619fe22-7152-4da6-b571-3efc29914936@googlegroups.com> |
| In reply to | #104664 |
On Friday, March 11, 2016 at 6:52:42 PM UTC-6, Gregory Ewing wrote:
> Rick Johnson wrote:
> > I have witnessed the mayhem that occurs when a language does
> > not mandate module encapsulation (Ruby, i'm looking directly
> > at you!!!!), and while i agree with the Python designers
> > that modules must *ALWAYS* be mandatory, i am not convinced
> > that module space should be so strictly confined to source
> > files.
>
> Well, I am. When looking at someone else's code, it's
> very useful to be able to take a name used in one source
> file and easily find the file where it's defined. That's
> very easy to do in Python, and very hard to do in languages
> that don't relate namespaces and source files.
You're essentially saying that all you have to do is scroll
up to the top of the current file, and find the line that
imports the symbol, and that line will tell you the name of
the module that contains the source code for that symbol.
Sure, that's reliable in most cases, but your argument
assumes that the actual source code for the symbol exists in
the module from which it was imported, when it could just as
well exist N-levels below that that module, due to chained
imports.
Imagine this scenario:
####################
# currentModule.py #
####################
from modX import foo
def bar():
return foo()
###########
# modX.py #
###########
from modY import foo
###########
# modY.py #
###########
from modZ import foo
###########
# modZ.py #
###########
def foo():
return 'O:-)'
I'll admit this is a highly contrived example, but it is not
invalid in anyway, and could therefore exist in reality. So
even though you will *EVENTUALLY* find the source code for
"foo", you would have to follow a long chain of imports to
get there. A more efficient method of finding the source,
would be to search your library for "def foo(", or, even
better, to utilize the tools available in the stdlib.
PY> import Tkinter as tk
PY> import inspect
PY> inspect.getsourcefile(tk.Frame)
C:\Python27\lib\lib-tk\Tkinter.py
Your editor should have tools for doing both of these
searches, and, if it's worth it's weight in salt, it will
even open the file for you.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-03-13 08:10 +1100 |
| Message-ID | <mailman.44.1457817037.12893.python-list@python.org> |
| In reply to | #104715 |
On Sun, Mar 13, 2016 at 3:49 AM, Rick Johnson
<rantingrickjohnson@gmail.com> wrote:
> Imagine this scenario:
>
> ####################
> # currentModule.py #
> ####################
> from modX import foo
>
> def bar():
> return foo()
>
> ###########
> # modX.py #
> ###########
> from modY import foo
>
> ###########
> # modY.py #
> ###########
> from modZ import foo
>
> ###########
> # modZ.py #
> ###########
> def foo():
> return 'O:-)'
>
> I'll admit this is a highly contrived example, but it is not
> invalid in anyway, and could therefore exist in reality.
I've never seen public symbols deliberately being imported through
multiple levels like this. The most I've seen is __init__.py pulling
stuff in from one of its modules (eg "from .constants import *"), or a
Python module importing from its accelerator ("from _socket import
*"). In theory, I suppose you could have both at once, but that's the
most you'd ever get, and the three would be very tightly coupled.
Otherwise, this simply doesn't happen.
Also, if currentModule.py is pulling foo from modX, then modZ.py is an
implementation detail. You don't necessarily want to go straight
there; tracing the chain is more likely to be the correct behaviour.
Suppose modX.py actually looks like this:
if 'posix' in some_magic:
import posixY as modY
elif 'nt' in some_magic:
import ntY as modY
else:
raise ImportError
The correct way to find out where modX.foo comes from is to look at
this block, not to jump right through it. Law of Demeter - you take
things one step at a time (unless there's a good reason).
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2016-03-12 19:36 -0800 |
| Message-ID | <69479550-3abf-4a11-a583-1cc549220b08@googlegroups.com> |
| In reply to | #104726 |
On Saturday, March 12, 2016 at 3:10:49 PM UTC-6, Chris Angelico wrote: > Also, if currentModule.py is pulling foo from modX, then modZ.py is an > implementation detail. You don't necessarily want to go straight > there; tracing the chain is more likely to be the correct behaviour. > Suppose modX.py actually looks like this: > > if 'posix' in some_magic: > import posixY as modY > elif 'nt' in some_magic: > import ntY as modY > else: > raise ImportError Ha, well, along with my example, this is another good example of a very bad design ;-). It's a terrible sin to import a symbol through multiple modules, but to import a symbol through multiple modules *AND* redefine it along the way, well, that should be punishable by the fatal exception. No judge, no jury. Just swift, and absolute, justice. :-)
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2016-03-13 15:05 +1100 |
| Message-ID | <mailman.55.1457841930.12893.python-list@python.org> |
| In reply to | #104745 |
On Sun, Mar 13, 2016 at 2:36 PM, Rick Johnson <rantingrickjohnson@gmail.com> wrote: > On Saturday, March 12, 2016 at 3:10:49 PM UTC-6, Chris Angelico wrote: >> Also, if currentModule.py is pulling foo from modX, then modZ.py is an >> implementation detail. You don't necessarily want to go straight >> there; tracing the chain is more likely to be the correct behaviour. >> Suppose modX.py actually looks like this: >> >> if 'posix' in some_magic: >> import posixY as modY >> elif 'nt' in some_magic: >> import ntY as modY >> else: >> raise ImportError > > Ha, well, along with my example, this is another good > example of a very bad design ;-). It's a terrible sin to > import a symbol through multiple modules, but to import a > symbol through multiple modules *AND* redefine it along the > way, well, that should be punishable by the fatal exception. > No judge, no jury. Just swift, and absolute, justice. :-) Good. Go complain to the os module about how it's doing the wrong thing. This is exactly what it does to provide os.path. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Gregory Ewing <greg.ewing@canterbury.ac.nz> |
|---|---|
| Date | 2016-03-14 12:35 +1300 |
| Message-ID | <dkmbpvF6tvkU1@mid.individual.net> |
| In reply to | #104715 |
Rick Johnson wrote: > Sure, that's reliable in most cases, but your argument > assumes that the actual source code for the symbol exists in > the module from which it was imported, when it could just as > well exist N-levels below that that module, due to chained > imports. Unless the module is doing something obscure, you can still find it by following the chain of imports. And since Python culture encourages rather shallow module nesting trees, the chain is usually fairly short. True, it's not *always* that easy, but in the vast majority of cases it is. The situation is certainly much better than what you have in e.g. a large C project, where you get *no idea* where a particular symbol may have come from by inspecting the source. -- Greg
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2016-03-14 15:55 -0700 |
| Message-ID | <c1538a50-3a8c-4b66-bbb6-bc4473b22be5@googlegroups.com> |
| In reply to | #104791 |
On Sunday, March 13, 2016 at 6:35:40 PM UTC-5, Gregory Ewing wrote: > Unless the module is doing something obscure, you can > still find [it's source file] by following the chain of > imports. [...] True, it's not *always* that easy, but in > the vast majority of cases it is. I agree you have a valid point, but i'll maintain that in no way, does this help to relieve the confining nature of these tightly wrapped "python module diapers", that we are all forced to wear. If our "Python motto" is to be, that we're "all adults", and we can trust our "siblings", and hopefully, *ourselves*, not to fiddle with aspects of our interfaces that are considered private, and, private by nothing more, mind you, than mere *convention*, then why do we take the opposite approach for modules, and force *ALL* code into a mandatory "one-size fits all" source file? Our ideology seems to be inconsistent here. Either we are adults capable of defining our own code, or we are immature babies who need mommy Python to protect us from every evil. But we cannot claim to be both. And don't misunderstand me, neither form of convention is "wrong". For instance, Java adopts a strict convention for writing code, but Java never claimed that it was a language that promoted "freedom". However, here in the Python community, we are constantly blabbing about how free we are, when in fact, our freedom is mostly a delusion. We need to stop making these false "claims of freedom". Heck, the only group of people more deluded about their own freedom, are my fellow Americans (Sometimes i really hate this country!) Python does not encourage freedom. Sure, we enjoy more "degrees of freedom" than say, your average Java programmer, but we must still submit to the many inconsistent whims of the Python interpreter. Outside of indention, we can't define how our code blocks will be structured. And, outside of nasty hacks, we can't decide how our module source files will reflect run-time module namespace. But most disturbing of all, there is no way possible, to protect the internals of our interfaces from public meddling. Many programmers don't understand *WHY* internals need to be protected. They will scoff at the idea, and they will claim that, by limiting *THEIR* ability to meddle with internals, *YOU* are robbing *THEM* of *THEIR* freedom. But what they don't realize, is that, the only crime worse than failing to create a proper interface, is to attempt to repair that failure *EXTERNALLY*. *ALL* repairs and *ALL* new features must be designed from *WITHIN* the object that exposes the interface, and from a strict internal perspective *ONLY*. Whether or not your language allows it, the following contractual obligations must *NEVER*, *EVER* be broken: (1) Callers can freely make requests to fetch or mutate a value, but they are forbidden from fetching and/or mutating the value directly. Only the object exposing the interface is capable of knowing how best to execute the request. If the caller finds that an accessor is missing, then the caller should beseech the source code maintainer to add the feature, or, they should add the feature themselves. But whoever adds the feature, they *MUST* do so in a manner that will not violate the basic contract between "callers" and "objects exposing an interface". (2) How a request is fulfilled, should be of no concern to an external caller. The only obligation the caller should expect of an interface, is that, when a formal request is sent, that a concerted attempt to fulfill the request will be made, and, if the request cannot be fulfilled, then a suitable explanation must be offered explaining why the request could not be fulfilled. You see, the object exposing the interface is *ALWAYS* submissive to the requests of any caller, but, if the caller attempts to break the "accessor contract", by entering the domain of the object exposing the interface, the object must block the invader by any means necessary, up to, and including, the fatal exception. Basically, the object exposing the interface adopts an attitude of: "Look, i'll do anything you ask me, so long as you ask me one of the questions posted on the door, but you have to make a formal request, you *CANNOT* just enter this sacred place at will, and start meddling with my levels and knobs, because if you do, you could cause a chain reaction that will destroy the delicate balance of our universe. I've had the unfortunate experience of maintaining code that did not utilize "strict interfacing contracts". Heck, for a good example of what *NOT* to do, have a look at the idlelib. (1) BAD STRUCTURE: A clear hierarchical structure is missing. It's spaghetti code, plain and simple. (2) COMPONENT COUPLING: Components are too tightly coupled, preventing easy plug-in and/or removal. (3) EVENT BINDINGS FIASCO: Instead of creating a "central interface" for which *ALL* event bindings would route on their way to the main editor widget, the author simply applied the bindings "in the shadows", from within various modules throughout the libray. Not only is this sort of design intuitive, it obfuscates important structural details, and it's one of the many reasons why this library has rotted for the last 20 or so years! (4): EXPORTABLE WIDGETS: Many of the widgets that were created for this library would have been useful to Python Tkinter GUI programmers over the years, however, they are missing much needed documentation, and some are written too specifically to be of use outside of IDLE (without heavy modifications). Granted, many of these widgets, like the Notebook and Balloon, have been offered by TIX for sometime, but Tix does not offer anything like Calltips, GrepDialog, ReplaceDialog, ClassBrowser., etc... But the most important is the Interactive Shell, which, if properly componentized, could be utilized to inspect code at run-time. It already has syntax coloring, calltips, code completion, and what have you. Heck, just the other day on Python-list, someone was opining for exactly that! (5): GENERAL TOOLS: A few general tools exist that could be used in other project.. That's all i can think of at the moment, but it hardly scratches the surface of what ailes this horrible stdlib module. Heck, i forgotten more sins of idlelib, than most people know about it. IDLE is a major failure, and i am saddened that it has existed in this state for such a long time.
[toc] | [prev] | [standalone]
Page 3 of 3 — ← Prev page 1 2 [3]
Back to top | Article view | comp.lang.python
csiph-web