POV-Ray : Newsgroups : povray.off-topic : This is the sort of brokenness... Server Time
10 Oct 2024 00:18:42 EDT (-0400)
  This is the sort of brokenness... (Message 75 to 84 of 164)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>
From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 13:03:50
Message: <49c27af6$1@news.povray.org>
Warp wrote:
>   I started by defending data hiding principle in the object-oriented/modular
> programming paradigm, and stressed that this principle is completely
> independent of the language used.

We did kind of get into a bit of a flurry of messages there, didn't we?

Let's see. I think we started out with a comment that minimalist languages 
with powerful syntax (e.g., LISP) can implement things like OO without 
having it built in, by using closures for example. Then the subject of CLOS 
came up (which AFAIK doesn't use closures), with an indication that it's 
possible to access the private members with sufficient work.


You said
"""
   I think that the typical impossibility or difficulty in data hiding in
languages which do not have specific support for modularity is a sign that
the "OOP" is, after all, just a kludge.
"""
and later talked about how reflection makes it impossible to hide private 
variables and implying that clear and unambiguous naming conventions that 
everyone who codes in the language understands aren't sufficient.



I have agreed with that.  I think what we're disagreeing with is the degree 
to which the language implementation needs to enforce that modularity 
strictly, but if it does, that's better than a language that disallows it 
without enforcing it, because you can look at your code and see what it's doing.

I prefer being able to break the modularity with reflection, because it 
gives you lots of power you otherwise need to write a bunch of boilerplate 
to handle.

Lacking that, I prefer to have the modularity enforced, so I can reason 
logically about a piece of code and determine that it will work correctly 
even if there are bugs in other parts of code. I've had too many occasions 
where I spend days looking for bugs in my code only to find that someone 
else had scribbled over memory.  Or even, in one case, had printed up "now 
invoking Darren's code"[1] and then crashing out while prepping the 
arguments to my module.

Lacking that, you have glorified assembly language. :-) The machine 
represented to your code matches the machine it's running on. There are 
times when that's good, but my work lately has not been one of those times.

>   Your argument against this technique seems to be "since you can't completely
> guard against it in C++, it's as good as not having data hiding at all". As
> if C++ had anything to do with this issue.

There were examples given as "private". I don't know who started it, maybe 
not you. I was simply pointing out that it's as easy for someone to violate 
your encapsulation in C++ as in LISP because the compiler doesn't enforce 
encapsulation. You can't completely guard against it in C++, and you can't 
completely guard against it in CLOS (the LISP OO system under consideration) 
or Python. I don't see that big a difference, really.

>> Um, no, really, you can't. How do you prevent me from corrupting your 
>> private variables with a wild pointer?
> 
>   If you write standard-conforming C++, you won't have a wild pointer
> (unless you have a bug, of course).

No. If *everyone* writes standard-conforming C++, you won't have a wild 
pointer. In safe languages, it doesn't matter what you write, *I* can count 
on my library behaving as I wrote it. And, unfortunately, the C++ compiler 
may try to enforce "private", but it doesn't try to enforce 
standard-conforming C++.

If you call "accessing someone else's private variables on purpose" a bug, 
then you can't have standard-conforming Python that violates encapsulation 
without a bug, either.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 13:05:19
Message: <49c27b4f@news.povray.org>
Warp wrote:
> Nicolas Alvarez <nic### [at] gmailcom> wrote:
>> Instead of using private:, you could just add an underscore to internal
>> variables.
> 
>   But why would I want to do that? There's no benefit. There are only
> potential disadvantages.

He's saying that putting "private:" before the variables in a class 
declaration is equivalent to naming private variables with an underscore. In 
the first case, the compiler warns you if you use a private variable by 
mistake. In the second case, it's obvious from inspection. If you have
    x._y
in your code, you're doing something wrong. :-)

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 13:06:01
Message: <49c27b79@news.povray.org>
Warp escreveu:
> Nicolas Alvarez <nic### [at] gmailcom> wrote:
>> Warp wrote:
>>>   Why not? Having the compiler check for breaking of agreements (eg.
>>>   "don't
>>> access these variables") is much better than oral agreements. The compiler
>>> is much better at catching mistakes than you are.
> 
>> It's an underscore or something else clearly visible in the offending
>> (= private-data-using-) code, not an oral agreement.
> 
>   Ok, "written agreement" then, if you want to nitpick. Not much difference.
> Still not enforced nor sanity-checked by anyone or anything.

Here is where Larry Wall's quote really applies. ;)


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 13:14:28
Message: <49c27d74@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> I disagree. Now you've got a naming convention that isn't enforced that 
>> would mean something to people trying to read your code.
> 
>   You mean the naming convention *is* enforced by languages which do not
> explicitly support private data?

Not exactly.

In Python (and, AFAIK, LISP), getting to private functions, for example, 
requires you to explicitly name the module and private function, and say 
"pull them into my space."

However, you can get to private members without doing that.

Therefore, the convention is that private members are given names that 
indicate they're intended to be private. Private functions don't need that 
naming convention, because there's a list out there in the source code that 
distinguishes private from public. That list is only enforced by default, 
but you can work around it if you care to read the code and see what isn't 
exported, or if you grope into the generated code and look what's there.

Even if it were enforced in Python, the metadata is there to be used and 
abused. You can go into the data structures that make up the class or the 
instance and modify them, because that's exactly how the system works 
normally. The compiler works by building those data structures at runtime, 
so if the compiler can do it, so can you. That's why the original article 
talked about dynamic systems, i.e., systems that you can change at runtime.

For example (and very simplified), in Python, each object has a hashtable 
mapping the names of fields to their values. Each member object of each 
class and instance is in a hashtable. The hashtable is called "__dict__", so 
xyz.__dict__["hello"] is the same as xyz.hello. If you marked "hello" as 
private (even if you could), code could still get to it via __dict__. If you 
marked __dict__ as private, all kinds of meta stuff would break.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 13:33:12
Message: <49c281d8@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> He's saying that putting "private:" before the variables in a class 
> declaration is equivalent to naming private variables with an underscore. In 
> the first case, the compiler warns you if you use a private variable by 
> mistake.

  Could you give a concrete example of a compiler, of any OO language,
which will only *warn* (rather than give an error message) if you try to
access a member variable specifically marked as private from the outside?

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 13:35:20
Message: <49c28257@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> >   Ok, "written agreement" then, if you want to nitpick. Not much difference.
> > Still not enforced nor sanity-checked by anyone or anything.

> Here is where Larry Wall's quote really applies. ;)

  Since when have code sanity checks become a bad thing?

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 13:44:49
Message: <49c28491$1@news.povray.org>
Warp wrote:
>   The question here is: Are compiler-enforced private member variables a
> good thing in programming or not?

My argument, again, very specifically, is that there's a bunch of 
possibilities, not two:

1) They're enforced 100%. Nobody outside the class is capable of writing to 
or reading from a private variable. This provides maximum isolation at the 
expense of not having available at runtime lots of stuff the compiler knows 
at compile time that you might want to know (e.g., reflection type stuff). 
The benefit is you can debug modules in isolation.

2) They're enforced 100%, but people outside the class can read but not 
write them. This is a little more fragile to change, but still capable of 
being debugged in isolation, because other parts of the code can't break 
your invariants. Eiffel does this, but it's the same syntax (x.y) to 
reference the y member of x as it is to invoke the nullary member function y 
on x, so you don't need to do more than recompile the client code. (I think 
you can also say a variable is completely private, IIRC.)

3) They're enforced, but there are explicit mechanisms to bypass them, such 
as reflection. This is my personal preference, because it's easy to find the 
places in the code that might be breaking your invariants or might rely on 
your internal implementation, while providing the power of metadata. This is 
the C# and Java model.

4) They're enforced by the compiler but not by the runtime. This removes 
*both* the ability to debug your module in isolation *and* the ability to do 
metaprogramming that eliminates boilerplate by using the information the 
compiler has already calculated.

5) They're not enforced by the compiler or the runtime, but there are 
conventions and/or standards that make it obvious to everyone when you're 
breaking the data encapsulation, and the runtime ensures that you can only 
do this "on purpose". That is, the unenforced conventions (or enforced but 
bypassable mechanisms) ensure that the only way of breaking encapsulation is 
on purpose. This is almost as good as #3, except it may be harder to track 
down who is violating your invariants.

6) There's no convention, and all you have is documentation saying which 
bits are supposed to be private and which aren't. Worst of all possible 
worlds. Not very modular at all.

>   I think that your problem is that you have some kind of holy war against
> C++, and every single discussion about programming is always somehow turned
> to bashing C++.

Nope. Someone brought up C++ by talking about the compiler enforcing 
"private:". I was just pointing out that the compiler only enforces it in 
some ways, and not in the ways that I thought was also important for modularity.

I.e., there's two good reasons for modularity: future-proofing your code, 
and bug-proofing your code. You only talked about the former.

>   I defended data hiding in general, as a programming paradigm (and I made
> that pretty clear). Your very first reply to me was a reference to (and
> attack against) C++.

Err, no it wasn't. I simply said "LISP can use macros to simulate OO just 
like C++ uses constructors and destructors to do resource management."

> You certainly didn't wait. 

Sure I did. Go back and look what I said about C++ again. Really.

> access rights in C++ and why everything is better in all other languages.

I haven't said better. I said different. I'm talking about the things above, 
which have little to do with C++ except it's the only unsafe OO language I 
know of.

>   I'm honestly getting tired of your C++ tirades. Every single subject
> related to programming must somehow include C++ bashing, regardless of
> the subject. That's getting tiresome.

I'm really not trying to bash C++ here. If pointing out that C++ allows you 
to corrupt member variables with a bug is "bashing", then I guess I'm bashing.

>> So you're saying having non-portable ways of bypassing the typing is better 
>> than having portable ways of bypassing the typing?
> 
>   How do you even manage to twist my words to almost the exact opposite of
> what I'm saying?
> 
>   Where exactly do you see the word "better", or any kind of synonym or
> reference to it? That's completely your twisted invention.

OK. I'm just trying to communicate here. That's why I'm asking the question. 
It seemed to me that you preferred a language with unsafe behavior and 
compiler-enforced checks to one with safe behavior and no compiler-enforced 
checks.  I was asking whether that was the case. The right answer would be 
"No, that's worse" or "No, that's different but just as bad because..." or 
something like that.

I've never heard you call C++ a kludge OO language. I assumed you were 
excluding C++ from that criticism when you said a language that allows 
access to private members is a kludge OO.

AFAIK, using lambdas to implement OO (which you can do in Python or LISP) is 
the only mechanism I've seen that doesn't expose private instance variables 
outside the class. Everything else provides either reflection or undefined 
(or even well-defined) behavior to so do.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 14:02:52
Message: <49c288cc$1@news.povray.org>
Warp wrote:
>   I still can't comprehend what's so bad in the compiler doing the check
> that you don't access the private members.

If it's actually enforced (as in an error rather than a warning), it makes 
lots of things harder than they need to be, because the running code winds 
up with less information than the compiler had. You're throwing away half 
the work the compiler did once you generate the code, so you wind up with 
lots of boilerplate to enter into code things the compiler already knows.

If it's not enforced (i.e., it's a warning), then I don't see it as an 
improvement over a naming convention. People don't accidentally use x._y in 
their python code any more than they accidentally name something 
__builtin_printf in their C code. In CLOS, you actually have to go read the 
source code of the implementation of the class to see what member variables 
you can access, so it's not like you don't know you're violating encapsulation.

If it's *really* enforced (as in you actually can't get to private 
variables), it lets you do things like prove your program is correct and 
lets you do things like know you've got a bug in your module when an 
instance variable winds up with the wrong value.

If it's half-enforced, as in the compiler complains and won't compile the 
code, but there's ways to get around it anyway (on purpose or by mistake), 
then it's IMO the worst of all possible worlds. You'll spend hours or days 
trying to debug code that's already right because the client is convinced 
the other code they've written is bugfree and it's easier to blame you than 
to find the wild pointer in their own code. The whole idea of class 
invariants goes out the window.

Incidentally, I see little wrong with breaking encapsulation if you maintain 
the invariants. It makes it harder to upgrade in the future without changing 
the client, but that's the price you pay for it. If you can automate the 
access to where it doesn't hurt to change the client, it seems like a 
win-win to me.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 14:03:10
Message: <49c288de$1@news.povray.org>
Warp wrote:
>   You could, of course, take that pointer and start trashing the memory
> it's pointing to, but that would be rather pointless. Certainly not useful.

Sure. And that's how C does its OO design pattern. :-)

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 14:26:37
Message: <49c28e5d$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> He's saying that putting "private:" before the variables in a class 
>> declaration is equivalent to naming private variables with an underscore. In 
>> the first case, the compiler warns you if you use a private variable by 
>> mistake.
> 
>   Could you give a concrete example of a compiler, of any OO language,
> which will only *warn* (rather than give an error message) if you try to
> access a member variable specifically marked as private from the outside?

Sure. C# or Java. You get this warning that says "this won't compile."  So 
you use the reflection libraries instead, and it compiles. The compiler 
hasn't stopped you from accessing the private variable. It just stopped you 
from trivially accidentally accessing the private variable. (Python doesn't 
even prevent you from trivially accessing the private variable, but in 
practice it isn't a problem.)

I know what you're asking. I'm asking you to look at it from a slightly 
different point of view. Take a more general approach to what it means to 
get "a warning" than the usual "the compiler issues warnings and errors, and 
nothing else is meaningful."

Another example is, as I've been saying, C++. The compiler warns (and won't 
compile) if you access the private variable by name, but not if you 
intentionally or accidentally access the private variable by address. Again, 
I understand what you're saying, and I'm asking you to also try to 
understand what I'm saying, instead of thinking I'm only saying it to annoy 
you. This is really how I think about programming - what do I know, and what 
might be broken. That's why I dislike unsafe languages with undefined behavior.

-- 
   Darren New, San Diego CA, USA (PST)
   My fortune cookie said, "You will soon be
   unable to read this, even at arm's length."


Post a reply to this message

<<< Previous 10 Messages Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.