POV-Ray : Newsgroups : povray.off-topic : This is the sort of brokenness... Server Time
9 Nov 2026 15:04:33 EST (-0500)
  This is the sort of brokenness... (Message 51 to 100 of 164)  
<<< Previous 50 Messages Goto Latest 50 Messages Next 50 Messages >>>
From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 18:32:50
Message: <49c17692$1@news.povray.org>
Warp wrote:
> nemesis <nam### [at] gmailcom> wrote:
>> Rule #5:  Best documentation is the code. ;)
> 
>   In fact, precisely. If the code supports telling "this is the public
> interface", what better documentation.

Both Python and LISP and Java and C# provide for that. They just don't fail 
to provide defined mechanisms for bypassing that.

-- 
   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: 18 Mar 2009 18:34:01
Message: <49c176d9$1@news.povray.org>
Warp wrote:
>   And then you modify your class, and your pre-existing SOAP interface parser
> breaks.

No, it doesn't. Because the reflection library will change what it sends, 
and generate a new WSDL that the client will use to get the new interface. 
That's why it's done that way.

-- 
   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: 18 Mar 2009 18:34:59
Message: <49c17713@news.povray.org>
Warp wrote:
>   It's different because if you do it by mistake, nothing will tell you.
> (Except when your code breaks when you update the library.)

The things we're talking about generally don't allow it to be done by 
mistake. It's certainly not the case that reflection gets "done by mistake".

-- 
   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: 18 Mar 2009 18:49:55
Message: <49c17a93$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>>>> Or just using compiler-specific hackage to access the variables. 
>>>   That has been made rather difficult in practice.
> 
>> Err, has it? I can't say something like
>>    int * p = (int*) ((void*)(&yourInstance) + 32);
>> if I want access to whatever integer is 32 past the start of your class?
> 
>   You call that "easy"? To me it looks like garbage. You can't write code
> like that by mistake. You are deliberately writing non-standard code which
> triggers undefined behavior. You are not accessing a member variable, you
> are trashing memory.

Yes.  Of course, it could just look like
    alpha[i] = 32;
and you're equally screwed.  Or even
   &myInstance.update()
if my instance happened to be on the stack before but isn't now, and your 
instance is there instead.

Tell me why you think reflection can be done by mistake?

>   Well, if you want to intentionally break the modularity of your code with
> something like reflection, at the risk of breaking tons of code in the future,
> that's your choice.

Well, yes, that's kind of the point.

>   (If you use reflection to, for example, save the state of an object to
> a database to be retrieved later, haven't you kind of locked up the
> structure of that object? You can't make *any* changes whatsoever to it
> without breaking all the stored objects in the database. Doesn't sound
> very enhanceable to me.)

Without reflection, you have no generalized way to handle this. With 
reflection, you can write code that does the right thing. Of course this is 
simplified.

But the same is true of a manually-implemented class.

And when you're serializing something to (for example) store as a hidden 
field on a web page, chances are when you update the code whoever is in the 
middle of a session is going to break anyway.

Or, when you change the shape, you fix the database appropriately.

>   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.

So I'm not seeing why the compiler not checking for you intentionally using 
a private variable is *less* encapsulated than the compiler not checking you 
don't accidentally have a wild pointer. The "standards-compliant" Python 
code says "don't dick with the private variables of an instance unless you 
want code that's fragile when that class gets upgraded."

In my experience, I'd much rather use a language where the access rules are 
enforced, even if those access rules allow well-defined methods of getting 
at private variables, than to use a language where a mistake by one 
programmer breaks code in a completely unrelated programmer's module. That's 
just my experience, tho.

>> If the statement is "the compiler should error out on external access to 
>> private variables, but there should be a non-portable hacky and error-prone 
>> way to bypass it anyway, so you can't rely in your debugging efforts on what 
>> your code actually says," I'll just have to disagree with you there. :-)
> 
>   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?  C# is less encapsulated 
than C++, because C# has documented ways of intentionally getting to private 
variables, but C++ has only accidental compiler-specific ways of getting at 
private variables?

How about a declaration on a class that says "It's OK for someone to bypass 
the private declarations and use reflection on this class", while classes 
without that declaration would not be accessible from the reflection 
methods. What do you think of that idea?

-- 
   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: 18 Mar 2009 19:00:49
Message: <49c17d21$1@news.povray.org>
Warp wrote:
>   That's a hilariously bad example 

I was assuming you're smart enough to generalize what I'm saying here.

>>   And you're either screwed, or you bypass the private part to 
>> make it work knowing you'll break on the next release of the library.
> 
>   And exactly how would making the private members public help this?

If you could go thru the list of private variables and store the values, 
then later reassign them to how they were, you're golden, yes?

>>>   I disagree. There's no modularity if you can't enforce access rights.
> 
>> And you can't enforce access rights in C++, because nothing prevents wild 
>> pointers from clobbering anything in memory.
> 
>   You are nitpicking, and you know it.

No, I really don't understand. You seem to be arguing that a universal 
naming convention isn't sufficient to say you have encapsulation, but a lack 
of ability to keep others from changing your private variables by accident 
is not a hindrance to encapsulation.

You seem to be saying that it's "unmodular" to say you can only violate 
encapsulation on purpose via complex library routines intentionally designed 
for metaprogramming, but it's modular to let people violate encapsulation by 
accident?

>   If you write normal, standard-conforming C++, you can perfectly well
> enforce access rights.

Um, no, really, you can't. How do you prevent me from corrupting your 
private variables with a wild pointer?

class Alpha {
   int abc = 0;
   public: int get_abc() { return abc; }
}

You're telling me it's impossible for anyone to write code that would ever 
make an instance of Alpha ever return anything but zero when calling 
get_abc()?  Really??

If I do
   Alpha beta;
   memset(&beta, 33, 4);
   std::cout << beta.get_abc();
I'm still guaranteed to get a 0 printed? How did I violate the standard?

By "standard-conforming", do you mean "never accidentally have undefined 
behavior, like using a pointer after you've freed it"?

And the standard that you don't access other instances variables that start 
with an underline doesn't count as "standard-conforming"?

Note that if by "standard-conforming" you mean "never making a mistake", 
it's not *your* code that makes the mistake. It's someone else's. So now 
you're back to trusting everyone to not make mistakes in order to enforce 
encapsulation, aren't you? You can't enforce it on your own.

I'm really trying to understand here, ya know. I'm trying to get my head 
around it. Maybe I've just been away from compiled languages too long or 
something.

-- 
   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: 18 Mar 2009 19:09:26
Message: <49c17f26$1@news.povray.org>
Warp wrote:
>   (If you use reflection to, for example, save the state of an object to
> a database to be retrieved later, haven't you kind of locked up the
> structure of that object? You can't make *any* changes whatsoever to it
> without breaking all the stored objects in the database. Doesn't sound
> very enhanceable to me.)

Actually, thinking about it, in this particular case of pushing something 
out to a database, the usual method is to use reflection to create a class 
based on the database schema, then instantiate objects and populate them 
from the database. So changing the object means changing the schema, then 
fixing the code that accesses the private variables of the resultant 
instances so as to perform the business logic.

So your code for reading the schema might say "I'll create an object when 
you read a row. That object will have a class whose name is row_xyz if the 
table is named xyz. The fields will be col_abc and col_def if there are two 
columns named abc and def. The types will map from SQL to C# (or whatever) 
like so: ...  I'll provide a routine called "load(...)" for each indexed 
key, and one called "save()" that writes the object back and "del()" that 
deletes the row from the database. You write the routines that use the 
columns as you like."

So when you reorg the database using SQL, you automatically get a new class 
without having to write all the code to generate SQL statements populated 
with the values of private variables.

You could do this with a code generator, sure, but that's all reflection 
stuff really is - using the compiler and runtime at runtime instead of just 
compile time.

>   If you trash memory, you are writing non-portable, non-standard-conforming
> code. All bets are off. If you want to write code like that

*I* don't write code like that at all. Others do, then blame me when their 
bugs break the modularity of my code, making it misbehave. See the problem?


-- 
   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: 18 Mar 2009 19:13:51
Message: <49c1802f$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> 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.

There's a certain subset of valid C++ programs that don't change private 
instance variables from outside the class, namely those that don't 
accidentally invoke undefined behavior. And there's a valid subset of C# 
programs that don't change instance variables from outside the class, namely 
those that don't use the reflection libraries. Which do you think is harder 
to inspect to see what type of program you have?

>>>   I don't understand what you are saying. If a class in C++ does not expose
>>> a member array, then you can't get to that member array from the outside,
> 
>> int * p = (int *) 0x123456;
>> *p = 27;
> 
>> Find the bug in your code that's setting that member variable to 27.
> 
>   What member variable?

Whichever one my code just accidentally clobbered. If

> 
>> 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?

>   It enforces it as long as you don't deliberately try to bypass the
> compiler checks.

No. It enforces as long as you don't *accidentally* bypass the compiler 
checks at runtime. That's my point!  You *can* accidentally bypass the 
compiler checks.

>   Deliberately hacking yourself around the compiler checks requires more
> malice than using a public member variable which simply "shouldn't" access.
> 
>   It sounds like you are saying "since you can't enforce the privacy of
> the members in all possible cases, then they might just as well be public".
> That's BS.

No. I'm saying that in many of these types of languages, including C#, you 
can enforce the privacy except in cases where the caller goes to extreme 
lengths to bypass that privacy. You don't seem to like the idea that 
reflection violates encapsulation, but you seem perfectly happy with the 
idea that out of bounds array indecies violate encapsulation, simply because 
the standard doesn't say it enforces encapsulation in that case.

>>  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?

>> 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.  In Python, you put "export" in front 
of the list of names of public functions, and you don't put "export" in 
front of the list of names of private functions.

>> Or, in short, you can't protect against bad programmers
>   So let's deliberately make bad code?

No. You're assuming the C++ programmers only write standard-conforming code 
and never accidentally (or maliciously) bypass the type system with a 
runtime bug like a dangling pointer.

Yet you assume the programmer will use reflection to bypass encapsulation 
without understanding the drawbacks, or accidentally use a well-marked 
private variable, and thus encapsulation is broken.

It's a bit of a double-standard there, I think. That's why I'm a bit 
confused. I think I'm seeing what you're saying: I think you're saying 
"Ideally, you can't bypass C++ private on purpose in a portable and 
standards-conforming way, while C# et al give you a standard way of doing 
so."  In my experience, this isn't nearly as helpful a distinction as you 
seem to have experienced.

-- 
   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: 18 Mar 2009 19:19:53
Message: <49c18199@news.povray.org>
Darren New wrote:
>>   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?

Or, to phrase it differently, do you know of any C++ compiler that won't 
clobber y with that code? Given that the layout of the class is required to 
  match the layout of the corresponding C structure (no virtual methods), 
the only real choices would see "clobber y", "dump core", or "do something 
completely unrelated to the C++ memory model."

... just to clarify. :-)

-- 
   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: Nicolas Alvarez
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 21:49:22
Message: <49c1a4a1@news.povray.org>
Warp wrote:
>   Don't write such BS. I am talking about experience. For example I have
> totally changed the internal implementation of this class of mine several
> times, and the public interface has always remained the same regardless,
> and thus the changes have never broken any existing code:
> 
> http://warp.povusers.org/FunctionParser/
> 
>   And by "totally" I mean literally write everything from scratch. And
> no external code breaks. That's the nice thing about modularity. It allows
> me to do that safely.

Instead of using private:, you could just add an underscore to internal
variables. It's not like someone would end up using one of those without
even noticing, so you don't necessarily have to write long documentation
explaining it. If someone used your "private" members, and his code breaks
when you rewrite your implementation, he gets to keep the pieces.

I'm just saying languages with no compiler- or runtime-enforced data hiding
aren't that bad. I'm definitely not suggesting people just add an
underscore when they're using a language that *does* have real private
data.


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 21:52:44
Message: <49c1a56c@news.povray.org>
Warp wrote:
>   And if you don't prevent it, you are locking yourself out of ever trying
> to improve your module (without breaking tons of existing code).

Tons of existing code are intentionally accessing stuff they know is subject
to change?


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 21:57:04
Message: <49c1a670@news.povray.org>
Warp wrote:
> nemesis <nam### [at] gmailcom> wrote:
>> Warp escreveu:
>> > And again, you are hacking on
>> > purpose, trying to bypass the compiler checks, rather than using those
>> > checks to catch your mistakes.
> 
>> How this is any different from someone breaking a contract on purpose is
>> beyond me.
> 
>   It's different because if you do it by mistake, nothing will tell you.

If you're using an underscore-prefixed member in Python, you *know* it's
private. It's not "done by mistake".

Plus, those aren't in the documentation, so you'd have to read the source
code to figure out their names.


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 22:04:11
Message: <49c1a81b@news.povray.org>
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.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 22:05:23
Message: <49c1a863$1@news.povray.org>
Nicolas Alvarez wrote:
> If you're using an underscore-prefixed member in Python, you *know* it's
> private. It's not "done by mistake".

Actually, to use C++ terminology, that makes it protected. Two underscores 
makes it private. :-)

-- 
   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: Nicolas Alvarez
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 22:06:52
Message: <49c1a8bb@news.povray.org>
Darren New wrote:
> Warp wrote:
>>   I don't understand what you are saying. If a class in C++ does not
>>   expose
>> a member array, then you can't get to that member array from the outside,
> 
> int * p = (int *) 0x123456;
> *p = 27;

Undefined behavior.

> How about
> // Your code...
> class xyz {
>    public: int[10] x;
>    private int y = 0;
> }
> 
> // My code
>   xyz pdq;
>   pdq.x[10] = 27;

Undefined behavior.


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 22:08:32
Message: <49c1a920@news.povray.org>
Warp wrote:
>   Deliberately hacking yourself around the compiler checks requires more
> malice than using a public member variable which simply "shouldn't"
> access.

Deliberately accessing a private member through reflection is harder too.
And it's not "malice".

Deliberately accessing a private member by typing its name with the
underscore is not hard at all, but you'll know you're doing it, and if it
breaks it's your fault :)


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 23:33:02
Message: <49c1bcee$1@news.povray.org>
Nicolas Alvarez wrote:
> Undefined behavior.
> Undefined behavior.

Certainly. And that's my point. The C++ standard doesn't say "you can't get 
to private members of a class."  It says "We're not going to tell you a 
reliable and portable way of doing so."  That doesn't mean you can't access 
private variables - otherwise, we wouldn't have buffer overflows clobbering 
private variables in exploits, would we?

-- 
   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 10:33:11
Message: <49c257a7@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> >   You are nitpicking, and you know it.

> No, I really don't understand. You seem to be arguing that a universal 
> naming convention isn't sufficient to say you have encapsulation, but a lack 
> of ability to keep others from changing your private variables by accident 
> is not a hindrance to encapsulation.

> You seem to be saying that it's "unmodular" to say you can only violate 
> encapsulation on purpose via complex library routines intentionally designed 
> for metaprogramming, but it's modular to let people violate encapsulation by 
> accident?

  Actually I'm not saying that. I have nowhere saying that.

  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.

  Then somehow you started talking about C++ in particular and somehow the
conversation was drifted from a programming paradigm in general to the quirks
in C++ in particular. I have nowhere defended C++ in particular, but data
hiding in general, as a programming technique.

  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.

> >   If you write normal, standard-conforming C++, you can perfectly well
> > enforce access rights.

> 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).

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 10:34:39
Message: <49c257ff@news.povray.org>
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.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 10:37:28
Message: <49c258a8@news.povray.org>
Nicolas Alvarez <nic### [at] gmailcom> wrote:
> Warp wrote:
> >   And if you don't prevent it, you are locking yourself out of ever trying
> > to improve your module (without breaking tons of existing code).

> Tons of existing code are intentionally accessing stuff they know is subject
> to change?

  I still can't comprehend what's so bad in the compiler doing the check
that you don't access the private members.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 10:38:16
Message: <49c258d8@news.povray.org>
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?

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 11:08:34
Message: <49c25ff2@news.povray.org>
Darren New <dne### [at] sanrrcom> 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

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 11:09:34
Message: <49c2602d@news.povray.org>
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.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 11:20:41
Message: <49c262c8@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Warp wrote:
> > Darren New <dne### [at] sanrrcom> 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

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 11:29:12
Message: <49c264c7@news.povray.org>
Darren New <dne### [at] sanrrcom> 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

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

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 14:27:20
Message: <49c28e88$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> Warp wrote:
>>> Darren New <dne### [at] sanrrcom> 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?

Because there's two reasons for data hiding: (1) allow more flexibility in 
implementation, (2) allow easier debugging.

If you can violate my encapsulation, I don't see the data as especially 
encapsulated, is all.

>   Every single discussion about programming with you turns into C++ bashing,
> no matter what the subject.

I'm happy to bash any other unsafe OO language you might want to name. :-)

>   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.

Yep. Can you name a C++ implementation that doesn't change "y" in that 
sample? I'm 100% serious here, because I know of C interpreters, but I've 
never seen a C++ interpreter. Or is there a tool that would catch that at 
runtime?  It would make some sorts of debugging a lot easier. I don't think 
purify handles that sort of thing, does it? It seems like it would be 
difficult, because the size of pointers would have to change or the shape of 
the structure would have to be incompatible with C.

>>>>  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.

I'm used to thinking about the semantics of a program. It's easy to 
miscommunicate when the semantics of a language include "there are no 
semantics for this valid piece of code that compiles cleanly."

It's untrue that "trying to access a private variable gives a compiler 
error." It's only true if you try to access the private variable in the 
obvious way. It's not true if you explicitly or accidentally circumvent the 
runtime system.

> "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.

I said "the compiler warns you in some cases that you're accessing private 
variables of other classes, and it doesn't warn you in other cases that 
you're accessing private variables of other classes." You want to make that 
into a discussion about whether it's a "warning" or an "error".

The compiler only gives you error messages if you break encapsulation in 
*some* ways, not in other ways.  I.e., only when you break encapsulation on 
purpose does it give you a warning. When you break encapsulation by mistake, 
it doesn't. If you access a private variable by name, it won't compile. If 
you access a private variable by address, it compiles fine.

When you break encapsulation in CLOS on purpose, you don't get a warning, 
but you know you're doing it because you're groping around in the source 
code of the class you're violating. I don't see how making that uncompilable 
can help.

Explain that to me? Really, without treating it as an attack, explain to me 
how requiring a programmer to read the source code (not header) of the 
module to discover the names of private variables isn't sufficiently 
encapsulated, compared to something enforced at compile-time but not 
runtime? It's discussions like this that lead me to a better and deeper 
understanding of the craft. :-)

>> 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.

And in CLOS, it's also source code. The only way to break encapsulation is 
go read the source code to see what the private variables are. It's not 
something you do accidentally, any more than you accidentally
#define private public.

-- 
   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:36:35
Message: <49c290b3$1@news.povray.org>
Warp wrote:
> 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?

When they become something to work around, rather than a help to the 
programmer. If you need to go read the source code of the module you're 
accessing to figure out how to get to the private variables, it's no longer 
a "code sanity check" IMO.

-- 
   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 15:00:54
Message: <49c29666@news.povray.org>
Darren New escreveu:
> Warp wrote:
>> 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?
> 
> When they become something to work around, rather than a help to the 
> programmer. If you need to go read the source code of the module you're 
> accessing to figure out how to get to the private variables, it's no 
> longer a "code sanity check" IMO.

Err... I think here I'll have to agree with Warp.  Why would you try to 
bypass the "code sanity checks" and all the paranoid safety devices to 
access something you shouldn't be accessing in the first place?

This thread has long derailed into something quasi-metaphysical... :P

My final word here is:  to have modularity you don't need all the traps, 
contraption devices and alarmist chainballs with all the barroque syntax 
associated.  All you need is to agree to use only what a module provides 
you.  It's your choice to be dumb enough or a smartass h4x0r and rip the 
contract just to show you can.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 15:26:04
Message: <49c29c4c$1@news.povray.org>
nemesis wrote:
> Darren New escreveu:
>> Warp wrote:
>>> 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?
>>
>> When they become something to work around, rather than a help to the 
>> programmer. If you need to go read the source code of the module 
>> you're accessing to figure out how to get to the private variables, 
>> it's no longer a "code sanity check" IMO.
> 
> Err... I think here I'll have to agree with Warp.  Why would you try to 
> bypass the "code sanity checks" and all the paranoid safety devices to 
> access something you shouldn't be accessing in the first place?



Because, every once in a while, the provider of the library wasn't omniscient.

It's pretty simple. It's a practical thing. Say you have (just for an 
example) a video codec. It does all kinds of nice things with timestamps and 
such, but one thing it doesn't provide is telling you the current frame 
number. However, that is stored in a private variable (which you can see 
from reading the .h file), and for some reason you need that information to 
implement your player in an environment the original author didn't intend 
his player to be used in.

You have three choices:
1) Violate encapsulation, and pay the price if you ever need to use a new 
version of the decoder that doesn't have the frame number in the same place.

2) Rewrite the entire video decoder from scratch.

3) Find the owner of the original code and get him to change it and agree to 
support it indefinitely.

It's a cost vs benefit thing.


You "shouldn't" be accessing the internal data structures NTFS stores on the 
disk. It makes it kind of hard to make an open source NTFS driver without 
doing so. If your systems *really* prevented that access, such drivers would 
be impossible to write. When MS changes the NTFS drivers, Linux maintainers 
have to go in, reverse engineer things again, and fix stuff up to stay 
compatible. That's a cost that wouldn't be borne if Microsoft's NTFS was 
open source and there was only one code base.

Sure, if you have the source code to the module, providing public access to 
the private variable is pretty easy. I'd not recommend bypassing the 
protection mechanisms in that case. I thought that would be obvious to 
people, tho, so I assumed everyone was on the same page with me there. 
(Which is not to say anyone disagrees or has disagreed with that here.)



> This thread has long derailed into something quasi-metaphysical... :P

I'm thinking it's something very practical. I'm not advocating regularly 
accessing the internals of other objects. I'm just saying that preventing it 
by convention or by hiding information from the humans isn't any worse IMO 
than implementing it in the compiler.

> My final word here is:  to have modularity you don't need all the traps, 
> contraption devices and alarmist chainballs with all the barroque syntax 
> associated.  All you need is to agree to use only what a module provides 
> you.  

And to be able to tell easily when you're violating it. If you have to read 
prose documentation to know whether some routine or variable is private or 
public, *then* you lack modularity.

-- 
   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 15:42:15
Message: <49c2a017$1@news.povray.org>
Darren New escreveu:
> nemesis wrote:
>> Err... I think here I'll have to agree with Warp.  Why would you try 
>> to bypass the "code sanity checks" and all the paranoid safety devices 
>> to access something you shouldn't be accessing in the first place?
> 
> Because, every once in a while, the provider of the library wasn't 
> omniscient.

You can also try another library. ;)

> And to be able to tell easily when you're violating it. If you have to 
> read prose documentation to know whether some routine or variable is 
> private or public, *then* you lack modularity.

Speaking purely from the point of view of Scheme and functional 
programming, there's no such a fuss:  all the module provides are public 
functions.  You just read their names and parameters and use them.

You can see from this thread that while it began with CLOS, it ended in 
C++ because of its tons of private, protected, friend and other 
schizophrenic access mechanisms leading to complicated interfaces and 
behavior for modules.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 15:58:29
Message: <49c2a3e5$1@news.povray.org>
nemesis wrote:
>> Because, every once in a while, the provider of the library wasn't 
>> omniscient.
> 
> You can also try another library. ;)

Well, yeah.

> You can see from this thread that while it began with CLOS, it ended in 
> C++ because of its tons of private, protected, friend and other 
> schizophrenic access mechanisms leading to complicated interfaces and 
> behavior for modules.

Actually, I thought it ended in C++ because that's the only unsafe OOP 
language I know of. It's the only language I know where the compiler 
attempts to enforce modularity but in practice fails to do so, by declaring 
violation of modularity "undefined" or "compiler-specific" rather than 
catching all cases of broken modularity at compile time or runtime.

I was trying to figure out how well-documented modularity breaking is a 
"kludge" but poorly documented unsupported modularity breaking isn't.

-- 
   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 15:59:47
Message: <49c2a432@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> >   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."

  Wait. The compiler gives a *warning* which says "this won't compile"?
If it's just a warning, and not an error, it means that it will compile
it anyways? Isn't that contradictory?

> Another example is, as I've been saying, C++. The compiler warns (and won't 
> compile) if you access the private variable by name

  I get no warning if I try to access a private member. I get an error.
There's a big categorical difference.

>, but not if you 
> intentionally or accidentally access the private variable by address.

  You can't access the private variable by address. Not according to the
standard. If you can, then that can be considered a non-standard compiler
extension.

  And trashing memory, triggering UB, is not the same thing as "accessing
a member variable". The effect may be the same as accessing in one compiler,
but might not be in another. You are not *really* accessing it. You are
just abusing compiler and system specific undefined behavior.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 16:01:19
Message: <49c2a48f$1@news.povray.org>
Warp wrote:
>   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.

Actually, let me ask this. Since you seem to be saying that reflection means 
that an OO system is a "kludge" because it breaks modularity, can you tell 
me what language *you* think isn't a kludge in this respect? Since the 
discussion mentioned "private:" and you defended the practice, I may have 
wrongly assumed that indicated that you thought C++ wasn't a kludge OOPL in 
this respect.

I don't know of any language that actually enforces modularity to the extent 
where it's impossible to write code that depends on private variables of 
another class, especially one to which you have the source. Every 
language[1] where the trivial ways of doing this (e.g., reading the source 
and using private names from outside the class) are enforced also has the 
ability to bypass it without too much trouble (either by using reflection or 
pointer arithmetic).

I don't know of any languages that make it trivially easy to *accidentally* 
confuse private and public member variables, except *perhaps* PHP and Perl, 
both of which I'll happily admit are kludges. :-) They might not make it 
trivial, I don't remember, but if they do, I'm not surprised.


[1] except perhaps Ada - I'd have to go look closer to see if unchecked 
conversions can do that sort of thing on tagged records.

-- 
   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 16:06:24
Message: <49c2a5c0@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> 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.

  That's the whole idea in modular thinking: You don't know what's inside
the module, and you *don't care*. You don't need to care.

  As soon as you start worrying what's inside the module, you are already
breaking module boundaries and abstraction.

> 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.

  No you'll explain to me how a naming convention of public variables helps
this problem.

> 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.

  IMO if anyone feels the need to break your interface and access private
members directly, then your class design sucks and should be redesigned.

  If your class design is good, nobody will need to access anything
directly.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 16:25:27
Message: <49c2aa37@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> 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). 

  If you need to know the private members of the class from the outside,
then that class has been badly designed.

  With a well-designed class you don't *need* to know, nor care.

> 2) They're enforced 100%, but people outside the class can read but not 
> write them. This is a little more fragile to change

  It breaks modularity badly. The whole idea of data hiding is that the
private part should be completely opaque to the outside. The second it
isn't, outside code will start making assumptions, and you can't change
the implementation of the class anymore.

> 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.)

  Some people argue that accessors to all private members, especially if
they are automatically generated, is almost as bad as having all the
members public. It exposes the internal implementation, and thus outside
code will start making assumptions about it, making it harder to change
the implementation later.

  Some accessors may be justifiable, but you should not go overboard.

> 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.

  If you don't have access to the code which is making assumptions about
your class' internal structure, you can't change your class without breaking
that existing code.

  Sure, this situation might not be extremely common, but it can happen.
And it's something which might have been avoided with a good interface
design and a completely opaque private implementation.

> 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.

  Why would you want runtime checks if access rights could be fully checked
at compile time?

> 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.

  Again, if you must keep "reverse compatibility", for a lack of a better
term (in other words, you as a library developer must maintain compatibility
with existing code which uses your library, and you don't have access to
this existing code nor can change it), it can be a problem if the existing
code can make assumptions about your library and does so.

> >   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.

  You immediately assumed that it must be talking about C++, of course,
and immediately jumped at the opportunity of bashing it.

> >   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.

  In a discussion about the modular programming paradigm and data hiding you
succeeded in creating an lengthy thread about how you can trash memory in C++.
It's not exactly like you avoided the subject.

> 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.

  That "you preferred a language with unsafe behavior" is 100% your own
invention. I have nowhere said that.

  What I have said is that I prefer enforced modularity over non-enforced
one (which IMO is not modularity at all). That "unsafe" bit is all your
own twisting.

> 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.

  At least you admit you are making assumptions.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 16:31:09
Message: <49c2ab8d@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> You can see from this thread that while it began with CLOS, it ended in 
> C++ because of its tons of private, protected, friend and other 
> schizophrenic access mechanisms leading to complicated interfaces and 
> behavior for modules.

  No. You just listed the excuses, not the real reason. The real reason
is that some people here really like to bash C++ at every possible
opportunity they can get. It's like a hobby to them. Or an obsession.

  I certainly didn't bring up C++. It's only after the bashing started
that I got dragged into the discussion about it.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 16:38:03
Message: <49c2ad2b@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> >> 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?

> Because there's two reasons for data hiding: (1) allow more flexibility in 
> implementation, (2) allow easier debugging.

> If you can violate my encapsulation, I don't see the data as especially 
> encapsulated, is all.

  You didn't answer my question.

  "Is enforced data hiding a good thing or a bad thing?"
  "In C++ you can bypass the encapsulation, so it's a bad thing."

  That doesn't make any sense. Exactly how is C++ related to the subject?
You are badly derailing.

  But of course. As long as you get to bash C++...

> >   Every single discussion about programming with you turns into C++ bashing,
> > no matter what the subject.

> I'm happy to bash any other unsafe OO language you might want to name. :-)

  It's getting really tiresome and old.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 16:50:32
Message: <49c2b017@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Actually, let me ask this. Since you seem to be saying that reflection means 
> that an OO system is a "kludge" because it breaks modularity

  In fact I said that trying to emulate OOP in a language which has no
direct support for OOP is a kludge. The only thing I said about reflection
is that IMO it breaks modularity and thus you lose many of the benefits of
modular design.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 16:54:00
Message: <49c2b0e7@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Actually, I thought it ended in C++ because that's the only unsafe OOP 
> language I know of.

  I can't understand if that means "I haven't studied unsafe OOP languages
other than C++" or "to my knowledge there are no other unsafe OOP languages".

> It's the only language I know where the compiler 
> attempts to enforce modularity but in practice fails to do so, by declaring 
> violation of modularity "undefined" or "compiler-specific" rather than 
> catching all cases of broken modularity at compile time or runtime.

  Then you don't know much, do you.

> I was trying to figure out how well-documented modularity breaking is a 
> "kludge" but poorly documented unsupported modularity breaking isn't.

  The connection between my usage of the word "kludge" and your usage
of the words "unsafe" and "reflection" is purely your invention.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 19 Mar 2009 17:00:33
Message: <49c2b271$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>>>   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."
> 
>   Wait. The compiler gives a *warning* which says "this won't compile"?
> If it's just a warning, and not an error, it means that it will compile
> it anyways? Isn't that contradictory?

No. That's why I'm saying you have to look at it from a slightly different 
perspective. It's a compiler error to access the private variable the *easy* 
way, just like in C++. It's not a compiler error to access the private 
variable in the *difficult* way. Hence, you are *warned* when accessing the 
private variable that you have to go out of your way to do it a different 
way.  The modularity isn't enforced at compile time.

>> Another example is, as I've been saying, C++. The compiler warns (and won't 
>> compile) if you access the private variable by name
> 
>   I get no warning if I try to access a private member. I get an error.
> There's a big categorical difference.

To you. Not to me. There are compiler flags that change warnings to errors. 
Does that mean they're not warnings any more?

>> , but not if you 
>> intentionally or accidentally access the private variable by address.
> 
>   You can't access the private variable by address. Not according to the
> standard. If you can, then that can be considered a non-standard compiler
> extension.

// So....
class xyz {
  int i;
} pdq;
memset(&pdq,23,sizeof(int));
// That's illegal C++ code?? I thought C++ is compatible with C?
// Surely the compiler has enough info there to refuse to compile
// it if it's illegal? Doesn't a class with no virtual members have
// to have the same memory layout as in C? How do you pass a struct
// to read(2) or write(2) if you can't take its address?

>   And trashing memory, triggering UB, is not the same thing as "accessing
> a member variable".

I'm not saying I'm "trashing memory". I agree it's triggering UB, but that, 
IMO, means C++'s encapsulation is as much of a "kludge" as CLOS's is. I 
mean, if you're agreeing that C++'s OOP is a kludge also due to lack of 
encapsulation, then sure, every OOP I know of is a kludge under those 
definitions. They're just kludgey in different ways.

I'd rather have the kind where you have to intentionally violate 
encapsulation in a way that is portable and makes it easy to see who is 
doing it, than have the kind that a simple bug can violate encapsulation in 
a module utterly unrelated to where the bug is.

And it's not about C++ vs other things, it's about safe vs unsafe languages. 
The only reason I brought up C++ is it's the only language I know that 
*doesn't* give you a well-defined way to work around the modularity in times 
of need.

What OO language besides C++ do you think doesn't have a kludgey modularity 
system? Any?

> The effect may be the same as accessing in one compiler,
> but might not be in another. You are not *really* accessing it. You are
> just abusing compiler and system specific undefined behavior.

And using reflection isn't *really* accessing it? Or is it? (That's a 
question of your opinion, not a rebuttal.)

As I said, I see what you're saying. I'm trying to generalize a bit more. 
Unsafe languages don't provide encapsulation of modules, IMO. The best they 
do is to prevent you from accessing private variables in a straightforward 
easy to understand way, without preventing you from accessing them in a 
contorted and non-portable way.   And since you're accessing the internals 
of someone else's code anyway, you've already decided to take on the problem 
of changing your access routines when the module changes, so the fact that 
it isn't portable when you change compilers doesn't seem like that much of a 
drawback to me, if the need arises.

It seems to be perfectly valid to use memcpy to copy the contents of an 
Alpha class into an array of characters that's sizeof(Alpha) and then pull 
out from that the values of any variables I need without violating the 
standard. It's non-portable, because I need to change the access routines 
when I change compilers, but ... I know that.

I wouldn't do that sort of thing if I had a choice. Certainly I wouldn't 
publish source code that intentionally takes advantage of this sort of 
undefined behavior. :-)  But then, I wouldn't publish source code that 
depends on the internals of someone else's CLOS code either.



Maybe here's something we can both agree on: Violating modularity can be a 
kludge. That doesn't mean that mechanisms to allow that give you a kludgey 
language. I'll grant that a language that makes it hard to know you're 
violating encapsulation is a kludgey language in that respect. I'll grant 
that any program that accesses private C++ variables or private CLOS 
variables from outside their class is a kludge. I think we'll have to agree 
to disagree on whether the mechanisms that *allow* such access (such as 
reflection) are inherently kludges.


IMO, it also doesn't mean that every violation of modularity is a kludge. If 
your violation of modularity doesn't violate the class invariant and it 
automatically adjusts to new releases of the class you're violating without 
further programming, I don't consider that a kludge. (Otherwise, for 
example, debuggers would be "kludges" by definition, and I don't think 
that's a reasonable assessment.)

-- 
   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 17:23:43
Message: <49c2b7df$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> 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.
> 
>   That's the whole idea in modular thinking: You don't know what's inside
> the module, and you *don't care*. You don't need to care.

It also prevents code from *inside* the module from doing certain things in 
an easy way.

>   As soon as you start worrying what's inside the module, you are already
> breaking module boundaries and abstraction.

Not if you're doing it from inside the module.

>> 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.
> 
>   No you'll explain to me how a naming convention of public variables helps
> this problem.

The naming convention doesn't help that. The safety of the language helps 
that. In other words, what helps it is not the naming convention, but the 
fact that code that accesses private variables *must* use the naming 
convention to do so.

Then you can take the Python code you're running, and look for the string 
"._framenumber". If you don't find that, nobody outside your class is 
changing the framenumber, even by accident. (Simplified of course, but 
that's the idea.)

In the CLOS case, you can just look for the name of the private variable 
that you suspect is getting changed from outside. Or you can change the 
source code you have to consistently rename that private variable and run it 
again and get a useful indication of exactly where in the outside code it's 
violating your encapsulation.

In an unsafe language, I can have code that was compiled before I even wrote 
my class accidentally violate my class's encapsulation, and it'll be almost 
impossible to figure out what is going on if the program's big enough or if 
I don't have the source to that code.

I'm just less worried about intentionally violating modularity than 
accidentally doing so. When I do it on purpose, I know the cost/benefit 
trade-offs. Doing so may be a kludge, but there's reasons kludges get 
implemented in the commercial world.

(I've had server code written in unsafe languages where it would dump core 
on a segfault, and the providers wanted to blame it on the fact that the Xen 
kernel was on the machine. We weren't booting Xen, but they wouldn't even 
look at their code until we uninstalled that kernel. Just as an example of 
how people can avoid admitting their own bugs might be part of the problem.

Another time, the "calculation" part of the program did its work, clobbered 
memory, wrote on the screen "now generating report", tried to create the 
data file for the report generator, and crashed out in a way that locked up 
the machine. As the author of the report generator, I got to spend several 
*weeks* trying to figure out what it was before I discovered it was just the 
calc routines not knowing their own calling structure and hence returning to 
the wrong place on the stack at some point. This included printing out *all* 
of the code I'd written, about a 5" stack, and going thru line by line 
looking for bugs. (Found one, which wasn't the problem. :-) Another problem 
that wouldn't have happened in a safe language.)

If you're in a particularly hostile environment, the best way is to have 
well-defined class contracts in a safe environment that prevents the abusers 
from bypassing those contracts. If you're not in a hostile environment, you 
just get the author to agree to support revealing the private information 
you need.

>   IMO if anyone feels the need to break your interface and access private
> members directly, then your class design sucks and should be redesigned.

I agree.  That's why I say that CLOS allowing you to get to private members 
from outside the class *if* you read the source code to the class and know 
what they're called isn't, in practice, a problem.  The only time someone 
would do that is if for some reason they can't *change* the source (because, 
perhaps, they're expecting an update), but they can't get the author to make 
an update that provides the interface that someone needs. At which point the 
only choice is (1) toss the entire module (rewrite, buy different version, 
etc), or (2) take on the burden of staying compatible with updates (which 
may be infrequent enough that it's in practice not a problem). It's a 
cost/benefit sort of thing.

>   If your class design is good, nobody will need to access anything
> directly.

I also agree. Or, at least, nobody will access anything directly without the 
author's "permission". If I say "it's OK to serialize this object, send it 
over the wire, and reconstitute it in another address space", I'd still say 
that's a good class design. If I'm worried about it getting stored for 
longer than the lifetime of the declaration of the class (i.e., the "stored 
in database" example), I'll write code to deal with it, or to convert the 
old versions to new versions.

-- 
   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 50 Messages Goto Latest 50 Messages Next 50 Messages >>>

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