Does Python really follow its philosophy of "Readability counts"?

Bruno Desthuilliers bdesth.quelquechose at free.quelquepart.fr
Sun Jan 18 12:22:06 EST 2009


Steven D'Aprano a écrit :
> On Sat, 17 Jan 2009 20:49:38 +0100, Bruno Desthuilliers wrote:
> 
>> Russ P. a écrit :

(snip)
>  
>>> Why leave to
>>> coding standards and company policy what can be encoded right into the
>>> language?
>> Because human are smarter than computers.
> 
> That's an awfully naive statement. It's a sound-byte instead of a 
> reasoned argument. We're smarter than computers?

Obviously and definitively, yes. Not that we are that smart - it's just 
that computers are totally stupids. The differences between a human and 
a computer are that
1/ a human can eventually DWIM.
2/ a computer can do what is has been told way faster than any human

The first point is being smart. The second is being fast. Not quite the 
same thing !-)

> Then why are we 
> programming in languages like Python instead of directly in machine code? 
> Why can optimizing C compilers make more efficient code than the best 
> human assembly language programmers?

Because :
1/ this is something that can be solved by heavy computations
2/ these computations can be programmed
3/ these compuations would just take too long for a human being to do 
manually

> Humans and computers are smart at different things.

s/smart/good/g

>>> Why leave to humans (who are known to err) what can be automated
>>> relatively easily? Isn't that what computers are for?
>> Error is human. For a real catastrophic failure, it requires a computer.
> 
> Oh rubbish. That's a sound-byte invented by nervous technophobes scared 
> of computers.

Nope, that's a computer-user joke.

> 
>>> All those "setters" and
>>> "getters" are a kludge. I think Python "properties" are a major step
>>> forward here. Just for fun, I checked to see if Scala has properties.
>>> Guess what? Not only does it have them, but they are generated
>>> automatically for all member data. That's even better than Python
>>> properties!
>> Oh yes ? "Better", really ? So it's better to have a language that
>> automagically breaks encapsulation (requiring an additionnal level of
>> indirection) than a language that do the right thing by default ? I'm
>> afraid I missed the point ???
> 
> You certainly do. How do properties "break" encapsulation rather than 
> enforcing it?

Properties by themselves are not the problem, quite on the contrary - as 
you say, they actually help wrt/ encapsulation. What breaks 
encapsulation is *automatic generation* for properties for *each and 
any* implementation attribute. Might as well just makes them all public 
attribute then.

> 
> 
>>>>> As I said before, enforced encapsulation may not be appropriate for
>>>>> every application, but it is definitely appropriate for some.
>>>> No. It is appropriate for dummy managers hiring dummy programmers. The
>>>> project's size and domain have nothing to do with it.
>>> Let me try to be very clear here. We are dealing with two separate but
>>> related issues. The first is whether data hiding should be added to
>>> Python.
>> No need to add it, it's already there : every name that starts with an
>> underscore is hidden !-)
> 
> That's not hidden. It's there in plain sight. 

Once again, I'm afraid you missed the joke - despite the smiley.

>>> Whether it can be added without screwing up the language, I don't know.
>>> If not, then so be it. That just limits the range of domains where
>>> Python is suitable.
>> That's just plain stupid.
> 
> No it's not. It's *practical*. There are domains where *by law* code 
> needs to meet all sorts of strict standards to prove safety and security, 
> and Python *simply cannot meet those standards*.

Oh, sorry. I was talking about *technical* issues, not about legal ones. 
IANAL...

(snip)

>>> I like to use the example of the flight software for a large commercial
>>> transport aircraft, but many other examples could be given. How about
>>> medical systems that control radiation therapy or chemotherapy? How
>>> about financial systems that could take away your retirement account in
>>> 1.5 milliseconds. Or how about the control software for the strategic
>>> nuclear arsenals of the US or Russia? When you consider the sea, air,
>>> and land-based components, I'm sure that's one hell of a lot of code!
>> And ? Such systems have been written (and quite a lot are still running)
>> with languages way more permissive than Python. You know, languages like
>> C or assembly. 
> 
> Yes, and it is *hard* because the programmer has to worry about data 
> hiding *on his own*.

Nope, it's hard because C and assembly are very low-level languages 
where you have to micro-manage each and everything. This has nothing to 
do with data hiding (unless you count memory management as data hiding ?)

> One of my friends has worked for many years programming some pretty high-
> powered banking software. Their approach is to move data-hiding into the 
> database, or the operating system. Cobol doesn't enforce encapsulation, 
> but the database and OS certainly do, with a permissions-based approach.

Guess what ? Whatever the language (Cobol, Java, Python, or even VB), 
chances are such an application would be written using a RDBMS (not even 
addressing the point about OS).

> Speaking of banking software, consider a typical banking application. It 
> may have dozens or hundreds of programmers working on it. It's too big 
> for any one person to understand all of it. Once deployed it may 
> potentially have access to hundreds of billions of dollars of other 
> people's money. Don't you imagine that one or two of these programmers 
> might be tempted to skim a little off the top?

There have been some major failure on such applications written with 
"serious" languages like Java. Know the sooo common "catch-all 
do-nothing exception handler" idiom in Java ?

> Data hiding is a good way of making sure that the guy writing the front 
> end can't just turn of the audit trail and transfer $60,000,000 into his 
> bank account.

Man, you can't be serious ? Tell me this is a joke ?

> 
>> Until you understand that *no technology is idiot-proof*,
>>   you'll get nowhere in "software engineering".
> 
> I suspect that Russ has got a lot further in software engineering than 
> you have.

Most of what is actually labelled as "software engineering" is snake 
oil. They're trying to sell you silver bullets. Now where's the werewolf?

> No technology is failure proof. But there's no reason in the world why 
> most technology can't be idiot-proof. Televisions are idiot-proof, 
> because they protect people from casual mistakes. If televisions were 
> built according to the Python model, the internals of the TV would be 
> exposed, without even a cover. All the major parts would be plug-in 
> rather than soldered in, and there would be no cover over the parts that 
> were live. Every year, tens of thousands of people would electrocute 
> themselves fatally (because parts of the TV holds a massive charge for 
> days after you unplug them from the mains) but that would be okay, 
> because you never know when somebody might want to pull out the fly-back 
> transformer and replace it with a six ohm resistor. That sort of dynamism 
> is important!

Really nice metaphor. Alas, there are limits to what you can do with 
metaphores.

(snip remaining)

> [...]
>>> An FMS programmer could perhaps
>>> decide to change the parameters of the engine controls, for example.
>> Why on earth would he do something so stupid ?
> 
> I'm sure he'd think he had a good reason. As you said, 
> 
> "Because sometimes you have a legitimate reason to do so and are ok to 
> deal with the possible issues."
>
> Maybe other people would disagree whether or not it was a legitimate 
> reason, or if he was OK dealing with the possible issues.
> 
> Perhaps he needed the extra optimization of skipping the getter/setters. 
> Perhaps he needed it for testing, and somehow one thing led to another. 
> Who knows?
> 
> It is strange that on the one hand you should insist that programmers 
> sometimes need to mess with internals, and on the other dismiss those who 
> do as "stupid". Your position is inconsistent.

Nope. My position is quite clear : just don't do something *stupid*. For 
a definition of "stupid" that is indeed highly dependant on the context 
(which you snipped).

> 
>>> To prevent that sort of thing from happening, the management could
>>> decree that henceforth all "private" variable names will start with an
>>> underscore. Problem solved, eh?
>> Certainly not. The only way to solve such a problem is to fire this
>> cretin.
> 
> Again, we shouldn't enforce encapsulation and data hiding

s/encapsulation//g

We were talking about language-enforced access restriction. Not about 
encapsulation.

> because there 
> are legitimate reasons for breaking it, but anyone who does break it is a 
> cretin. 

Not "anyone". Just those who do it where they obviously should not. And 
be sure that anyone cretin enough to mess with implementation *in the 
context mentioned by Russ* (context which, once again, you snipped) 
would find a "clever" way to do the same (or worse) in any language. You 
don't want such a smartass in your team, *specially* for critical stuff.

> You have a very strange attitude.

You have a very strange way of handling context.

> Besides, it's not very practical. When you fire "the cretin", it has 
> consequences. Everyone else in the project has to work harder,

My own experience is that firing an obvious cretin from a team leads to 
*less* work for the team - because then you don't have to re-read and 
rewrite all his code.


> [...]
>> Please educate yourself and learn about why Ariane 5 crashed on it's
>> first flight, due to an error in a module written in ADA (which is such
>> a psychorigid language that C++ and Java are even looser than Javascript
>> in comparison). Perhaps will it light a bulb for you.
> 
> Others have already pointed out that the error in the Ariane 5 rocket was 
> *human* error due to somebody messing with the internals, namely 
> defeating the compiler's default type checking.

This was *not* an error *in the context* this module was designed (and 
tested, QAd etc) for.

> I'd just like to ask: 
> Bruno, were you aware of the cause of the crash,

Yes I was. Else I wouldn't have mention it.

> and if not, why did you 
> raise the issue in the first place?

Because the problem had nothing to do with technology. Only with not 
being serious on specs / tests / QA. Hence my point : it's not because a 
module has been written using a technology (rightly) known for it's 
security and robustness that you can get by with non-technical issues.

> Did you think it was a compiler bug 
> that caused the crash?

Do you think I am a newbie ?


>>>>> Not
>>>>> every door needs a lock, but certainly some do.
>>>> You only need locks when you don't trust your neighbours.
>>> Yeah, if you live in Nome, Alaska.
>> Brillant. You obviously failed to understand the differences between
>> "software engineering" and real life. When it comes to computers, the
>> only doors I care closing are those which would let someone crack my
>> computer.
> 
> If only there was some way to know which bugs could let people crack our 
> computer and which bugs couldn't.
 >
> Anyway, that's your choice. Personally, I'd much prefer my software not 
> to cause data loss, not to crash, not to DoS me, not to hang, and not to 
> generate bogus data,

This is a different problem. Please don't mix bananas and screwdrivers.

>  
>> But FWIW, I never close my car. And, in case you don't know, it's
>> perfectly possible to access "private" members in Java (and, if you do
>> have access to the source code, in C++ too).
> 
> Yes, but it is more difficult. There's a larger psychological barrier. 
> It's easier to audit for such access, even in a large project. It 
> encourages a more careful attitude: "do I *really* need to mess with the 
> internals, or is there a safer way?". It forces the programmer to *think* 
> before doing something potentially dangerous.

This is a beautiful dream. Reality is that either the guy is wise enough 
to not do something he know he shouldn't without due thinking and 
consideration, or he is dumb enough to do something he shouldn't one way 
or another.

> This is why I wish eval and exec were in a module instead of built-ins. 

I do agree they shouldn't be builtins, but mostly because there are too 
few real use case for them to be builtins. (well, wrt/ exec, it's a 
statement to the problem is a bit different).

> Suppose Python worked like this:
> 
> 
>>>> class Parrot:
> ...     _private = 'spam'
> ...
>>>> p = Parrot()
>>>> p._private = 'ham'
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> ProtectionError: attribute is read-only from outside of class Parrot
>>>> from protection import unlock
>>>> unlock(p)._private = 'ham'
>>>> p._private
> 'ham'
 >
> 
> I don't know if this scenario is even possible in Python,

It actually isn't, at least not without way too much overhead messing 
with call stack (and even then...).

"Methods" need to freely access implementation attributes. But Python's 
"methods" are just wrappers around plain functions, which by themselves 
don't know (and shouldn't need to know) if they where defined within a 
class statement or not.

> but pretend 
> that it is.

Ok, let's pretend !-)

> Would it be so terrible?

No, I could live with it. Just a question now : how would this deal with 
functions defined outside the class statement but used as methods ?

Oh, and please read until the end...

> If a particular project wanted to 
> enforce encapsulation,

s/encapsulation/data hiding/

> all they need do is replace or remove the 
> protection module from their Python installations. (I assume the project 
> developers aren't *hostile*. If they are, then there's almost nothing you 
> can do to make the code safe. Encapsulation is about protecting from 
> accidents, not sabotage.)

InMyArms(tm) !-)

> If you wanted to mess with the internals in 
> your own project, all you need do is import a module.
> 
> 
> We could imagine the same scenario in reverse. Python allows getters and 
> setters, but they're more work,

And more overhead.

> and so people just don't use them unless 
> they really need to.

Which is fine. Well, MHO at least.

> Suppose Python offered real data encapsulation,

s/encapsulation/hiding/

> but 
> you had to work to get it:
> 
>>>> class Parrot:
> ...     _private = 'spam'
> ...
>>>> p = Parrot()
>>>> p._private = 'ham'  # allowed by default
>>>> from protection import lock
>>>> lock(p)._private
>>>> p._private = 'spam'
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> ProtectionError: attribute is read-only from outside of class Parrot
> 
> 
> Would that be so bad? I don't think so.

So technically, this means that you'd have an optionel check for 
_implementation attribute access outside methods ?

Good news my friend, Pylint already do this (and quite a lot of other 
things too...). So wrt/ code reviews, QA etc, the "lack of access 
protection" is not such an issue, is it ?


http://www.logilab.org/card/pylintfeatures
"""
W0212:	Access to a protected member %s of a client class
Used when a protected member (i.e. class member with a name beginning 
with an
underscore) is access outside the class or a descendant of the class where
it's defined.
"""




More information about the Python-list mailing list