![](/i/fill.gif) |
![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> > If you trash memory, you are writing non-portable, non-standard-conforming
> > code. All bets are off.
> You're making a mistake that is arguably easier to make than using a name
> that starts with an underline.
> That's exactly what I'm saying: If you make a mistake, all bets are off. So
> you're counting on the perfection of every author and contributor to your
> codebase to always do the write thing, because the compiler *doesn't* check
> that it's right, and the runtime *doesn't* check that it's right.
Your argumentation just doesn't make any sense.
The question here is: Are compiler-enforced private member variables a
good thing in programming or not?
Your argument why they are not: In C++ you can accidentally access them
regardless of the compiler checks.
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++. Thus every time you want to discredit some argument, you
go and explain why that thing is done wrong in C++, regardless of whether
C++ in particular was being discussed, or whether it was a more generic
discussion about programming.
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++. You certainly didn't wait. Now you have succeeded in
dragging this thread away from the original question, and made it about
access rights in C++ and why everything is better in all other languages.
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 also getting tired of you twisting what I say. I have admitted that
in C++ you can trash memory, triggering undefined behavior which might,
among other things, modify the state of an object. You somehow have managed
to twist this so that, according to you, I'm saying this is a good thing
(or somehow "better" than other means of accessing private members). I can't
understand where you are getting this. You are just arguing for the sake of
arguing. Example:
> > Where have I said "there should be a non-portable way to bypass it"?
> >
> > There may be a non-portable way of bypassing it. That's different from
> > "there should be".
> 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.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Nicolas Alvarez <nic### [at] gmail com> 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.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> Warp wrote:
> > Darren New <dne### [at] san rr com> wrote:
> >>> (Well, at least not without some serious hacking.)
> >
> >> Running off the end of an array is "serious hacking"? I wouldn't think so.
> >
> > Now I'm completely puzzled. We are talking about public interfaces and
> > private members, and you start suddenly talking running off the end of an
> > array? I can't see *any* connection whatsoever between these two things.
> I'm saying that C++ does not enforce that you don't change private instance
> variables from outside the class.
And this has exactly what to do with whether (compiler-enforced) data
hiding is a good thing or not?
Every single discussion about programming with you turns into C++ bashing,
no matter what the subject.
> >> How about
> >> // Your code...
> >> class xyz {
> >> public: int[10] x;
> >> private int y = 0;
> >> }
> >
> >> // My code
> >> xyz pdq;
> >> pdq.x[10] = 27;
> >
> > You are accessing a public variable, not a private one.
> Nope. Read it again. What exactly gets set to 27? Do you think there's a
> good chance it might by y?
You are accessing a public variable, namely the array named 'x'.
You are accessing it out of boundaries, triggering UB, after which the
compiler is free to do whatever it wants with your code. It may as well
draw an ascii mandelbrot for all the standard cares.
Could that perhaps change 'y'? Maybe. The standard allows the compiler
to do whatever it wants. If the compiler wants to change 'y', it has the
standard's blessing. If the compiler gives you an error message saying that
you are a moron, that's ok as well.
> >> The compiler doesn't enforce the
> >> encapsulation in C++ - it just gives warnings when you use a variable name
> >> that's private.
> >
> > Warnings? Trying to access a private variable gives a compiler error.
> Only if you do it in the obvious way. Or are you saying there's a
> compile-time warning for calling memset() with too large a size?
I'm just baffled about how you twist words. Exactly where am I saying
anything like that? I don't even understand how you can come with such a
conclusion. It doesn't make any sense.
"The compiler doesn't enforce encapsulation, it just gives warnings."
"Actually the compiler gives an error if you try to break encapsulation."
"Are you saying there's a compile-time warning for calling memset wrongly?"
"???"
I just can't follow your logic.
> >> Granted, if you don't *document* in a universal kind of way what's public
> >> and what isn't, you're leaving yourself open to abuse.
> >
> > That's the great thing about language support for private sections: You
> > don't *need* to document that they are private. The compiler will tell you.
> Sure you do. You have to put "private:" in front of the private bits and
> "public:" in front of the public bits.
Exactly how is that "documentation"? That's source code.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> or the infamous "#define private public"
Btw, if you *really* want to hide your private variables, there's a
technique used by some:
class MyClass
{
public:
// public functions here
private:
struct Members;
Members* members;
};
If the struct 'Members' is implemented eg. in a static or dynamically
loadable library, ie. you don't have the source code, it's extremely
difficult for anyone to even figure out what members there are in there
or how to access them. Your #define won't help at all here, nor accessing
the object by other means.
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.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Nicolas Alvarez <nic### [at] gmail com> 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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp escreveu:
> Nicolas Alvarez <nic### [at] gmail com> 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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Warp wrote:
> Darren New <dne### [at] san rr com> 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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> 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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
nemesis <nam### [at] gmail com> 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
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |
|
![](/i/fill.gif) |
| ![](/i/fill.gif) |
|
![](/i/fill.gif) |