POV-Ray : Newsgroups : povray.off-topic : This is the sort of brokenness... Server Time
6 Sep 2024 13:19:34 EDT (-0400)
  This is the sort of brokenness... (Message 51 to 60 of 164)  
<<< Previous 10 Messages Goto Latest 10 Messages Next 10 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

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

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