POV-Ray : Newsgroups : povray.off-topic : This is the sort of brokenness... Server Time
14 Oct 2026 02:59:41 EDT (-0400)
  This is the sort of brokenness... (Message 1 to 50 of 164)  
Goto Latest 50 Messages Next 50 Messages >>>
From: Darren New
Subject: This is the sort of brokenness...
Date: 16 Mar 2009 14:42:03
Message: <49be9d7b$1@news.povray.org>
... that I hate seeing in a popular language. Backwards compatibility for a 
language already rushed out the door is really a killer, IMO.

http://vijaymathew.wordpress.com/2009/03/13/dangerous-designs/

-- 
   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: 16 Mar 2009 15:14:58
Message: <49bea532@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> ... that I hate seeing in a popular language. Backwards compatibility for a 
> language already rushed out the door is really a killer, IMO.

> http://vijaymathew.wordpress.com/2009/03/13/dangerous-designs/

  In my little experience, trying to use a programming paradigm (eg. OOP)
with a language which has no specific support for that paradigm (eg.
traditional lisp or scheme, or C) only creates a ton of kludges.

  Also this:

"The argument is that, using a very small number of rules for forming
expressions and with a minimal syntax it is possible to support all
possible programming paradigms. For instance, if the language has
support for higher-order functions, closures and dynamic typing, we
can implement object oriented programming without special language
level syntactic support. Tail-call optimization elude the need for
special looping constructs."

sounds like you could argue in favor of languages like brainfuck which
have a minimal set of instructions, yet are still Turing-complete.

  Eg. just because tail recursion is enough to perform any kind of
looping construct doesn't necessarily mean that special looping constructs
wouldn't be a useful tool.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 16 Mar 2009 16:30:37
Message: <49beb6ed@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> ... that I hate seeing in a popular language. Backwards compatibility for a 
>> language already rushed out the door is really a killer, IMO.
> 
>> http://vijaymathew.wordpress.com/2009/03/13/dangerous-designs/
> 
>   In my little experience, trying to use a programming paradigm (eg. OOP)
> with a language which has no specific support for that paradigm (eg.
> traditional lisp or scheme, or C) only creates a ton of kludges.

Yeah, except these kludges are in the class files, because nobody wants to 
break the JVM to get new features. Alternately, you get things like .NET 
with a bunch of new features that are only available on Windows because 
people doing Mono need time (and motivation) to reimplement. Hard to say 
which mechanism is best.

> "The argument is that, using a very small number of rules for forming
> expressions and with a minimal syntax it is possible to support all
> possible programming paradigms. For instance, if the language has
> support for higher-order functions, closures and dynamic typing, we
> can implement object oriented programming without special language
> level syntactic support. Tail-call optimization elude the need for
> special looping constructs."
> 
> sounds like you could argue in favor of languages like brainfuck which
> have a minimal set of instructions, yet are still Turing-complete.

If it's fast enough and you have sufficiently flexible macros, sure. Kind of 
like the way C++ can use general purpose constructor and destructor 
semantics to implement resource management.

>   Eg. just because tail recursion is enough to perform any kind of
> looping construct doesn't necessarily mean that special looping constructs
> wouldn't be a useful tool.

I think if you look at the level he's speaking about here, i.e., the JVM 
level, that objection goes away.  Think about something like .NET only 
supporting tail recursion in the CIL - all the *languages* would translate 
looping stuff into tail recursion, just like right now C# translates 
closures into nested class declarations invisibly.

And if you're familiar with LISP, and the power of its macro system, you can 
see where he's coming from - LISP has a powerful looping construct (called 
LOOP :-) that expands internally into the definition of a tail-recursive 
function.

Something where you can't rewrite the source code at compile time to fit 
your needs? No, doesn't work out to make a bunch of minimal things. It also 
pushes the burden for figuring out optimizations back onto the runtime. For 
example, in a C-style for loop, you can tell by looking at the source code 
if there's an index variable that can be stored in a register and not pushed 
to memory on each loop. (In Pascal, it's trivial, for example, due to "for" 
being much simpler.) If you have a macro that turns every loop into tail 
recursion, then the runtime/JIT/whatever now has to analyze the variables 
coming in and the variables being passed in *all* the possible 
tail-recursive calls to see if there's one that might be serving as a loop 
index. On the other hand, you might also wind up with more opportunities to 
optimize something that would be harder to express in something like C, so 
the compiler needs to do as much work, but doesn't because the compiler 
authors spent more time on other types of optimization. Sort of the 
difference between generating optimal bytecodes from Java vs generating 
optimal machine code from bytecodes, given the entire context of the program.


-- 
   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: 16 Mar 2009 18:07:45
Message: <49becdb1$1@news.povray.org>
Warp wrote:
>   In my little experience, trying to use a programming paradigm (eg. OOP)
> with a language which has no specific support for that paradigm (eg.
> traditional lisp or scheme, or C) only creates a ton of kludges.

Actually, LISP has excellent support for OO. It has closures (which are 
objects without the types, not unlike javascript objects) and it has macros 
that let you Do The Right Thing with the syntax and integrate it cleanly 
into the language. It's not going to look like Java/C++/C#/etc classes, but 
I'd disagree it's a kludge.

I don't remember scheme enough to know how clean it is, and I'll agree with 
you on the C part. :-)  And that's not to say there aren't things that would 
be very difficult to do in LISP without native support built into the 
language (like some forms of control flow, for example).

-- 
   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: 16 Mar 2009 18:42:30
Message: <49bed5d6$1@news.povray.org>
Darren New escreveu:
> Warp wrote:
>>   In my little experience, trying to use a programming paradigm (eg. OOP)
>> with a language which has no specific support for that paradigm (eg.
>> traditional lisp or scheme, or C) only creates a ton of kludges.
> 
> Actually, LISP has excellent support for OO. It has closures (which are 
> objects without the types, not unlike javascript objects) and it has 
> macros that let you Do The Right Thing with the syntax and integrate it 
> cleanly into the language. It's not going to look like Java/C++/C#/etc 
> classes, but I'd disagree it's a kludge.

More than that, Common Lisp has CLOS:
http://en.wikipedia.org/wiki/Common_Lisp_Object_System

> I don't remember scheme enough to know how clean it is, and I'll agree 
> with you on the C part. :-)  And that's not to say there aren't things 
> that would be very difficult to do in LISP without native support built 
> into the language (like some forms of control flow, for example).

Are you kidding?  One of the main strenghts of Lisp is its macro system. 
  Not dumb C preprocessing, a metaprogramming features which allows you 
to create nice new syntax for any control flow you want.

See:
http://www.paulgraham.com/onlisp.html

Scheme itself lives up to its original goal as a minimalist and 
incredibly flexible and powerful language.  See for instance an 
implementation of a full-fledged, purely functional object-system:
http://okmij.org/ftp/Scheme/index.html#pure-oo

This is done purely with functions and will look awkward for Warp in the 
way they are called, but thing is:  one layer of macros later and it 
looks just as integrated into the language as if OO was always there.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 16 Mar 2009 19:12:58
Message: <49bedcfa$1@news.povray.org>
nemesis wrote:
> More than that, Common Lisp has CLOS:
> http://en.wikipedia.org/wiki/Common_Lisp_Object_System

Yes. I was trying to describe that it doesn't have to be built in, tho. :-) 
I like CLOS.

(I don't know if CLOS counts as "built in" or not.)

>> I don't remember scheme enough to know how clean it is, and I'll agree 
>> with you on the C part. :-)  And that's not to say there aren't things 
>> that would be very difficult to do in LISP without native support 
>> built into the language (like some forms of control flow, for example).
> 
> Are you kidding?  One of the main strenghts of Lisp is its macro system.

Didn't I say that? :-)

> http://okmij.org/ftp/Scheme/index.html#pure-oo

Cool. Thanks for 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: nemesis
Subject: Re: This is the sort of brokenness...
Date: 16 Mar 2009 20:35:01
Message: <web.49beefea11b2c188b5d35d190@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> (I don't know if CLOS counts as "built in" or not.)

It is.

> > http://okmij.org/ftp/Scheme/index.html#pure-oo
>
> Cool. Thanks for that.

That guy has all sorts of cool stuff, either in Scheme, Haskell or C++.

The "On Lisp" book by Paul Graham is very good too.  It's available in PDF and
explores Lisp macros as no other.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 16 Mar 2009 20:39:15
Message: <49bef133@news.povray.org>
nemesis wrote:
> The "On Lisp" book by Paul Graham is very good too.  It's available in PDF and
> explores Lisp macros as no other.

Yep. Got it, read it. :-) I wish I had a use for it. :-)

-- 
   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: 16 Mar 2009 21:15:02
Message: <49bef995@news.povray.org>
Warp wrote:
>   In my little experience, trying to use a programming paradigm (eg. OOP)
> with a language which has no specific support for that paradigm (eg.
> traditional lisp or scheme, or C) only creates a ton of kludges.

Heh, did you see the GObject framework?


Post a reply to this message

From: Nicolas Alvarez
Subject: Re: This is the sort of brokenness...
Date: 16 Mar 2009 21:18:30
Message: <49befa66@news.povray.org>
Darren New wrote:
> ... that I hate seeing in a popular language. Backwards compatibility for
> a language already rushed out the door is really a killer, IMO.
> 
> http://vijaymathew.wordpress.com/2009/03/13/dangerous-designs/

OMG, *that* is how they implemented it?!


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 16 Mar 2009 22:55:00
Message: <web.49bf10b311b2c188b5d35d190@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> nemesis wrote:
> > The "On Lisp" book by Paul Graham is very good too.  It's available in PDF and
> > explores Lisp macros as no other.
>
> Yep. Got it, read it. :-) I wish I had a use for it. :-)

Dude, slow down on that coffee! X^D


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 16 Mar 2009 23:28:23
Message: <49bf18d7$1@news.povray.org>
nemesis wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> nemesis wrote:
>>> The "On Lisp" book by Paul Graham is very good too.  It's available in PDF and
>>> explores Lisp macros as no other.
>> Yep. Got it, read it. :-) I wish I had a use for it. :-)
> 
> Dude, slow down on that coffee! X^D

Heh. Got it, read it many moons ago.

-- 
   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: 16 Mar 2009 23:29:28
Message: <49bf1918$1@news.povray.org>
Nicolas Alvarez wrote:
> OMG, *that* is how they implemented it?!

Yeah. Generics are kludged in approximately the same way, with the extra 
excuse that it allows generic code to interoperate with previously compiled 
non-generic code.

They've locked themselves into a specific JVM, and nothing can change that now.

-- 
   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: 17 Mar 2009 01:05:00
Message: <web.49bf2f4911b2c188b5d35d190@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
> sounds like you could argue in favor of languages like brainfuck which
> have a minimal set of instructions, yet are still Turing-complete.

Scheme:
Minimalist.  check
Power. check
Flexibility. check

Brainfuck:
Minimalist.  check

>   Eg. just because tail recursion is enough to perform any kind of
> looping construct doesn't necessarily mean that special looping constructs
> wouldn't be a useful tool.

That's why you got for-each in the standard and a few more. (which, obviously,
are macros wrapping tail-recursive calls)


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 03:51:05
Message: <49c0a7e9@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> More than that, Common Lisp has CLOS:
> http://en.wikipedia.org/wiki/Common_Lisp_Object_System

"Like the OO systems in most dynamic languages, CLOS does not enforce
encapsulation. Any data member (or slot) can be accessed using the
slot-value function or via (optionally auto-generated) accessor
methods."

  Your definition of object-oriented programming may vary, but in my view
data hiding, ie. modularity, is an integral part of OO programming. If the
internal structure of the object is exposed to the outside, you lose most
of the benefits of modularity.

  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.

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 12:44:25
Message: <49c124e9$1@news.povray.org>
Warp wrote:
>   Your definition of object-oriented programming may vary, but in my view
> data hiding, ie. modularity, is an integral part of OO programming.

It's pretty easy to fix in LISP if you really care - just make all your 
local names gensyms.  (If we're still talking about minimal support for lots 
of paradigms, you could do this with some pretty simple macros, methinks.)

CLOS doesn't do this, because people who use LISP are usually pretty good 
programmers.

> If the
> internal structure of the object is exposed to the outside, you lose most
> of the benefits of modularity.

Like, in unsafe languages, where a stray pointer can change private 
variables without going thru the class methods? :-)

By this factor, I know of almost no actual OO languages besides Smalltalk 
and Ada. (And Ada has OO features without being what I'd call an OO 
language.) And I'm not sure you can't cast pointers inappropriately in Ada, 
either. I'll look it up some day when I'm bored. :-)

C# and Java both have reflection that let you get to private members from 
outside. C++ not only lets you return pointers to private members (which 
isn't particularly bad in *my* opinion, see below, but you might disagree) 
but also allows unsafe (in the technical sense[2]) access to private members 
via undefined operations. It's pretty trivial to bypass all the modularity 
in C++ since you need to be able to see the class declarations of the 
private parts in order to access the class[1]. Python has the __dict__ 
element (et al) even if you had private variables.  Pretty much anything 
designed so you can serialize it has external access to private members.

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

Now, ya see, I see the point of modularity is to let me reason about the 
code. If I have a private integer X, and the only things I set it to are 0, 
1, or 2, then I should be able to have a switch with those three cases and 
never miss one. Or, for a better example, if I have a buffer, and my class 
is the only thing that writes to the buffer, I can ensure I never have a 
buffer overflow. This isn't the case in C++ any more than it is in LISP or 
Python. The only difference is, in LISP it's much harder to break by 
accident.  I don't see the advantage of making variables private if the 
privacy isn't enforced well enough to give me more guarantees about the 
program's execution. It's like having type declarations that aren't checked 
at compile time or runtime - what's the point?

It would seem to be no harder to track down a bug caused by someone 
accessing a private variable in a LISP object inappropriately than it would 
be to track down someone overflowing a public array and clobbering a private 
member in C++, especially since in LISP you'd actually have the name of the 
private member somewhere in the source code module causing the trouble.




What do *you* think modularity is good for, that simply saying "stuff that 
starts with an underline is private to the class" isn't adequate? I'm 
seriously asking, because I'm wondering if I'm missing something.




[1] For example, you could declare an identical class with a different name, 
except with all the privates public, then cast a pointer to the private 
class into a pointer to the public class. Don't even need to depend on 
compiler-specific knowledge about element layout and such. Or just declare a 
child class that is happy to change any of its private variables.

[2] "Unsafe" means there are features with undefined behavior which may 
affect the future state of the program, such that you can put values of the 
wrong type into variables. That is, you can put values that don't belong to 
the type into a variable of that type, or access values inappropriately 
(such as accessing private variables from outside the scope you're supposed 
to access them from).

-- 
   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: 18 Mar 2009 13:16:34
Message: <49c12c72@news.povray.org>
Darren New escreveu:
> Warp wrote:
>>   Your definition of object-oriented programming may vary, but in my view
>> data hiding, ie. modularity, is an integral part of OO programming.
> 
> It's pretty easy to fix in LISP if you really care - just make all your 
> local names gensyms.  (If we're still talking about minimal support for 
> lots of paradigms, you could do this with some pretty simple macros, 
> methinks.)
> 
> CLOS doesn't do this, because people who use LISP are usually pretty 
> good programmers.

Yes.  Straight-jackets are generally viewed as a limiting "feature" by 
people who actually know how to program rather than being a low-paid 
drone.  What really amazes me is when very smart programmers actually 
enjoy being in the jacket and ask for more. :P

The best I've ever read on the subject comes from Larry Wall:
"The trend over the last 25 years or so has been to design computer 
languages that enforce a state of paranoia.  You're expected to program 
every module as if it were in a state of siege.  Certainly there are 
some feudal cultures where this is appropriate, but not all cultures are 
like this.  In Perl culture, for instance, you're expected to stay out 
of someone's home because you weren't invited in, not because there are 
bars on the windows."

http://books.google.com.br/books?id=oh8lz4A3sUsC&pg=PA289&lpg=PA289&dq=larry+wall+house+invited&source=bl&ots=NcO4joArZd&sig=SaR-z_PriPfBbQaxNRAHpBfD_gc&hl=pt-BR&ei=dynBSYutLNuvtwfE0MXSCg&sa=X&oi=book_result&resnum=3&ct=result

Of course, such attitude would not stand the barbarism going on in 
enterprise by thousands of code monkeys typing a bad rerun of 
Shakespeare, but for one guy or 2 in the know alone working on a private 
project, giving up all bureacratic measures for you not to shoot your 
own foot may lead to an increased productivity with no sensible bug issues.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 13:30:28
Message: <49c12fb4$1@news.povray.org>
nemesis wrote:
> Of course, such attitude would not stand the barbarism going on in 
> enterprise by thousands of code monkeys typing a bad rerun of 

I think by the time you get people so disconnected from each other that you 
have to literally defend your code against them, you also have a 
sufficiently big management structure that you can afford code reviews and 
things like that. And if someone *does* need to bypass your API and access 
the private variables, chances are you can either (1) get them to change the 
implementation of the public API, or (2) if the author is (say) in another 
company, it's a good thing you can bypass the lack of ability to do what you 
need. :-)

-- 
   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 13:35:24
Message: <49c130dc@news.povray.org>
Warp wrote:
> "Like the OO systems in most dynamic languages, CLOS does not enforce
> encapsulation. Any data member (or slot) can be accessed using the
> slot-value function or via (optionally auto-generated) accessor
> methods."

BTW, this is only true in CLOS. If you actually implement OO using closures, 
this isn't the case.

As a sort of C++ equivalent, consider C++'s upcoming lambda expressions. If 
you write something like

{ int x, y;
   x = 3; y = 4;
   std::function pdq = [x,y](z) {return x+y+z;}
   x = 8; y = 9;
   // What here could you write to get the "4" that's in y inside pdq?
}

(Assuming I'm close on the syntax, and I think I'm saying pass x and y by 
value to the pdq lambda thingie.)

Building OO via closures is like that, except the x and y serve the purpose 
of instance variables. (C++ doesn't have actual closures, so the analogy is 
flawed here, of course, but if you don't see how closures can make objects, 
that should clarify it.)

If you could pass x and y by reference, declared several std::functions that 
used them by reference, and then return collection of those functions 
without actually losing the stack frame those referneces referred to, you'd 
have objects-on-closures, with no access to internal instance variables.

-- 
   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: Fredrik Eriksson
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 13:43:54
Message: <op.uqz0vkjo7bxctx@e6600>
On Wed, 18 Mar 2009 17:44:23 +0100, Darren New <dne### [at] sanrrcom> wrote:
>
> [1] For example, you could declare an identical class with a different  
> name, except with all the privates public, then cast a pointer to the  
> private class into a pointer to the public class. Don't even need to  
> depend on compiler-specific knowledge about element layout and such. Or  
> just declare a child class that is happy to change any of its private  
> variables.

Except that the compiler is not required to generate the same layout in  
those two cases, so you would still depend on compiler-specific knowledge.


-- 
FE


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 15:28:02
Message: <49c14b41@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> CLOS doesn't do this, because people who use LISP are usually pretty good 
> programmers.

  No. Crappy programmers (self-taught "hackers") want everything exposed and
can't understand the reasoning behind data hiding. Good programmers understand
this reasoning and for that reason use data hiding and abstraction.

> > If the
> > internal structure of the object is exposed to the outside, you lose most
> > of the benefits of modularity.

> Like, in unsafe languages, where a stray pointer can change private 
> variables without going thru the class methods? :-)

  No. The reasoning behind data hiding in modular thinking is completely
independent of the language used. It has to do with program design.

  If you expose the internal structure of a module to the outside, then
there's a big chance that outside will start making *assumptions* about
this internal structure. As an example, a module describing the concept
of a "color" might have four integral variables as members, one for each
color component. If this fact is exposed to the outside, then there's a
big chance that some code somewhere will assume that the "color" module
has four integral member variables with certain names.

  If this happens, then you can't change the internal implementation of
this module without breaking existing code. For example, if you wanted
to change the color components to floats, or you would want to pack the
color components into one single integral value, you will most probably
break existing code (especially probable in the latter case, as the
amount and names of the member variables will change drastically).

  If you can design the absolutely perfect module which will never change
its contents and will suffice for years to come, then by all means make
all members public. Us mortals will try smarter techniques.

> C# and Java both have reflection that let you get to private members from 
> outside.

  Thus it's one reason why the design of these languages is badly broken.

> C++ not only lets you return pointers to private members

  Only if the class itself explicitly does so. You can't get to the private
members *from the outside*. (Well, at least not without some serious
hacking.)

  It's usually considered bad design in C++ to return pointers to members.

> Now, ya see, I see the point of modularity is to let me reason about the 
> code. If I have a private integer X, and the only things I set it to are 0, 
> 1, or 2, then I should be able to have a switch with those three cases and 
> never miss one. Or, for a better example, if I have a buffer, and my class 
> is the only thing that writes to the buffer, I can ensure I never have a 
> buffer overflow. This isn't the case in C++ any more than it is in LISP or 
> Python. The only difference is, in LISP it's much harder to break by 
> accident.  I don't see the advantage of making variables private if the 
> privacy isn't enforced well enough to give me more guarantees about the 
> program's execution. It's like having type declarations that aren't checked 
> at compile time or runtime - what's the point?

  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,
and if the class' own functions are properly designed, no buffer overflow
is possible (precisely because you *can't* access the array from the
outside).

> What do *you* think modularity is good for, that simply saying "stuff that 
> starts with an underline is private to the class" isn't adequate? I'm 
> seriously asking, because I'm wondering if I'm missing something.

  You might be able to control your *own* code from not misusing public
variables (and you might never make mistakes), but it's more difficult to
control someone else.

  If you need to tell someone else "don't access member variables whose
name start with an underscore", that's just plain stupid. You should be
able to tell that by making the *compiler* enforce it.

-- 
                                                          - Warp


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 15:33:07
Message: <49c14c73$1@news.povray.org>
I'm sorry, but that simply doesn't follow.  If the guy is stupid enough 
to use things not in the interface I give him, it's his problem if he's 
f*cked down the road.  But I agree with you:  dumb programmers like that 
should wear a straight jacket, no doubt.


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 15:33:53
Message: <49c14ca1@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> Yes.  Straight-jackets are generally viewed as a limiting "feature" by 
> people who actually know how to program rather than being a low-paid 
> drone.

  No, data hiding is seen as "limited" by self-taught hackers who don't
know jack s**t about programming. Those people just can't understand what's
the idea, and want everything to be accessible.

>  What really amazes me is when very smart programmers actually 
> enjoy being in the jacket and ask for more. :P

  I enjoy being able to create modules which I can safely improve later
without the fear of breaking existing code. And I'm talking from actual
experience, rather than theorethical handwaving.

> The best I've ever read on the subject comes from Larry Wall:
> "The trend over the last 25 years or so has been to design computer 
> languages that enforce a state of paranoia. You're expected to program 
> every module as if it were in a state of siege.

  What a load of BS.

> Of course, such attitude would not stand the barbarism going on in 
> enterprise by thousands of code monkeys typing a bad rerun of 
> Shakespeare, but for one guy or 2 in the know alone working on a private 
> project, giving up all bureacratic measures for you not to shoot your 
> own foot may lead to an increased productivity with no sensible bug issues.

  Increased productivity... until the day that you actually need to heavily
change some module because of new requirements or improvements, and you end
up breaking thousands of lines of code which are carelessly using public
members as they please.

  Of course rather than admit their design mistake, they will just use some
fancy term for this, such as "refactoring".

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 15:41:12
Message: <49c14e58@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> I'm sorry, but that simply doesn't follow.

  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.

-- 
                                                          - Warp


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 15:56:16
Message: <49c151e0$1@news.povray.org>
Warp escreveu:
> nemesis <nam### [at] gmailcom> wrote:
>   No, data hiding is seen as "limited" by self-taught hackers who don't
> know jack s**t about programming. Those people just can't understand what's
> the idea, and want everything to be accessible.

It's not because it's accessible that it is going to be used.  It is 
only accessible because the implementation didn't care to bother putting 
loads of chains and belts and bureaucratic measures that are there only 
for the sake of bad programmers who can't understand the concept of 
interfaces and have to have their knees broken so they can't jump the fence.

For people who know it better, the lack of such measure does not mean 
irrestrict access to things, it simply means less stupid typing to make 
the compiler happy.  Modularity is conserved.

>   I enjoy being able to create modules which I can safely improve later
> without the fear of breaking existing code.

Why would you fear breaking your own modular code with clear interface? 
  Are you yourself using things you shouldn't?  Why are you blaming the 
implementation then?

>   Increased productivity... until the day that you actually need to heavily
> change some module because of new requirements or improvements, and you end
> up breaking thousands of lines of code which are carelessly using public
> members as they please.

It's all about scope.  If it's public, it should be used.  If it's not, 
you shouldn't.

Scheme/Lisp has no problem with any of that though.  First because of 
lexical scoping:  if you need to use an accessory function, you can 
simply declare a local lambda in the outer function and no outside 
functions will reach it.  Second, because modules are truly modules and 
though you may declare many functions, you only explicitely export some 
of them.  And functions not exported are truly not exported, you can't 
reach them, using whatever dirty hacks you wish.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 16:19:12
Message: <49c15740$1@news.povray.org>
Warp wrote:
>   Increased productivity... until the day that you actually need to heavily
> change some module because of new requirements or improvements, and you end
> up breaking thousands of lines of code which are carelessly using public
> members as they please.

In languages other than LISP (say, Python or PHP or whatever), this is 
handled by having a naming convention saying what variables are to be 
treated as private.

I'm not sure I see the benefit of "I use private: in my C++ classes" to "I 
put an underscore before private names in my classes."  Other than a touch 
of readability (which many C++/Java/etc programs violate by tacking things 
like "m_" to the front of every member variable) I don't see a whole lot of 
difference.

Certainly if should-be-private members are exposed as public but don't 
document to the user which are private, that's a 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 16:20:58
Message: <49c157aa$1@news.povray.org>
Fredrik Eriksson wrote:
> Except that the compiler is not required to generate the same layout in 
> those two cases, so you would still depend on compiler-specific knowledge.

You still get subclasses. And of course there's always the hack of declaring 
a subclass. Or just using compiler-specific hackage to access the variables. 
or the infamous "#define private public". But correction noted. It's just 
irrelevant to the point I was making. :-)

-- 
   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: 18 Mar 2009 16:23:31
Message: <49c15843@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> Warp escreveu:
> > nemesis <nam### [at] gmailcom> wrote:
> >   No, data hiding is seen as "limited" by self-taught hackers who don't
> > know jack s**t about programming. Those people just can't understand what's
> > the idea, and want everything to be accessible.

> It's not because it's accessible that it is going to be used.

  Yeah, sure. If you are the *only* person making the entire program, then
perhaps that might be the case.

>  It is 
> only accessible because the implementation didn't care to bother putting 
> loads of chains and belts and bureaucratic measures that are there only 
> for the sake of bad programmers who can't understand the concept of 
> interfaces and have to have their knees broken so they can't jump the fence.

  So in your opinion the concept of "interface" is a verbal agreement about
what should and shouldn't be used from a module? *That* is what sounds like
bureaucracy to me.

  And why is a verbal agreement better than telling the compiler about the
interface?

> For people who know it better, the lack of such measure does not mean 
> irrestrict access to things, it simply means less stupid typing to make 
> the compiler happy.  Modularity is conserved.

  In Utopia, maybe. In the read world, not so.

  And I don't consider having to write "private:" once to be significantly
more typing. If I had to document what you should and should not access
in the module, *that* would be significantly more typing. And the kind of
text which most people will not read anyways.

> >   I enjoy being able to create modules which I can safely improve later
> > without the fear of breaking existing code.

> Why would you fear breaking your own modular code with clear interface? 

  Maybe you, Mr. Perfect, never make mistakes. I like the compiler telling
me possible mistakes, especially since telling the compiler what the interface
of my module is, is rather simple.

  Also, if I make a module for others to use, how can I guarantee that
I can change the implementation later without breaking code others have
written? There are two options:

1) I write "private:" once in my class definition.

2) I write extensive documentation about the subject and hope people will
   read it and obey it. Many people won't.

  Which one of these two options is easier and less trouble?

> >   Increased productivity... until the day that you actually need to heavily
> > change some module because of new requirements or improvements, and you end
> > up breaking thousands of lines of code which are carelessly using public
> > members as they please.

> It's all about scope.  If it's public, it should be used.  If it's not, 
> you shouldn't.

  And what's wrong with the compiler telling you if you try to use it
regardless? I really can't understand that.

  The compiler is not limiting anything that you aren't *already* limiting
by your verbal agreement. The only thing the compiler is doing is checking
that the agreement is not broken. Why that is a bad thing is beyond my
comprehension.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 16:28:52
Message: <49c15984@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Certainly if should-be-private members are exposed as public but don't 
> document to the user which are private, that's a problem.

  I thought you were old enough to know some basic facts of life:

Rule #1: People *don't* read documentation.
Rule #2: Read rule #1.
Rule #3: Even if people read documentation, they do not have photographic
         memory and they forget.
Rule #4: Humans are imperfect and make mistakes.

  Why is it a bad thing to make the compiler check interface breaches is
beyond my comprehension. It's enormously easier to do than writing some
documentation and *hoping* that people will read and obey it, and never
make mistakes.

-- 
                                                          - Warp


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 16:31:06
Message: <49c15a0a$1@news.povray.org>
Warp escreveu:
> nemesis <nam### [at] gmailcom> wrote:
>> I'm sorry, but that simply doesn't follow.
> 
>   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.

Now I (think I) understand the root of our disagreement.  I'm thinking 
about functional programming here with only functions accessible per 
interface, you're thinking about what variable can be accessed and 
whatnot in a severely mutable setting.  It all becomes really hard when 
you allow state to dominate.  So hard that even very experienced 
programmers can face dificulty handling it all, thus having to invent 
all sorts of levels of accessibility rather than just rely on lexical scope.


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 16:32:22
Message: <49c15a56@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> You still get subclasses. And of course there's always the hack of declaring 
> a subclass.

  A subclass can't access the private members of the base class.

> Or just using compiler-specific hackage to access the variables. 

  That has been made rather difficult in practice. If you are *intentionally*
trying to break your program, then that's your choice, of course. However,
in normal usage it's useful if the compiler checks that you don't make
mistakes.

> or the infamous "#define private public".

  Whether your program will link after that can depend on the compiler.
It's certainly not standard-conforming. And again, you are hacking on
purpose, trying to bypass the compiler checks, rather than using those
checks to catch your mistakes.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 16:36:10
Message: <49c15b3a@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> Warp escreveu:
> > nemesis <nam### [at] gmailcom> wrote:
> >> I'm sorry, but that simply doesn't follow.
> > 
> >   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.

> Now I (think I) understand the root of our disagreement.  I'm thinking 
> about functional programming here with only functions accessible per 
> interface, you're thinking about what variable can be accessed and 
> whatnot in a severely mutable setting.  It all becomes really hard when 
> you allow state to dominate.  So hard that even very experienced 
> programmers can face dificulty handling it all, thus having to invent 
> all sorts of levels of accessibility rather than just rely on lexical scope.

  Not all member functions have to be public either. It's extremely common
for a class to have private member functions which are part of its internal
implementation and not even intended to be part of the public interface.

  I would say that being able to define private member functions is equally
important as being able to define private member variables.

-- 
                                                          - Warp


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 16:58:57
Message: <49c16091$1@news.povray.org>
Warp escreveu:
> nemesis <nam### [at] gmailcom> wrote:
>> It's not because it's accessible that it is going to be used.
> 
>   Yeah, sure. If you are the *only* person making the entire program, then
> perhaps that might be the case.

Like I said, if the dumbass wants to use things not in the interface, 
it's his risk.

>   So in your opinion the concept of "interface" is a verbal agreement about
> what should and shouldn't be used from a module? *That* is what sounds like
> bureaucracy to me.

Not bureaucracy at all.  Just a list of names of functions a module 
provides.

>> For people who know it better, the lack of such measure does not mean 
>> irrestrict access to things, it simply means less stupid typing to make 
>> the compiler happy.  Modularity is conserved.
> 
>   In Utopia, maybe. In the read world, not so.

Indeed.  In real enterprise world we got people who don't enjoy nor know 
how to program, programming.  Or, should I say?, fill up a few forms and 
allow an IDE to generate the code.  It will spill shit all over, true.

>   And I don't consider having to write "private:" once to be significantly
> more typing.

Indeed, Delphi and C++ are yet more zippy at that, not so much for those 
poor Java souls... you also forgot the data type declarations.

> If I had to document what you should and should not access
> in the module, *that* would be significantly more typing.

This coming from a guy whose favorite language needs for one to provide 
the source and the header file.

 > And the kind of
 > text which most people will not read anyways.

It's usually the first thing one sees when opening a module.  (export 
foo bar boz frob etc)

>   Also, if I make a module for others to use, how can I guarantee that
> I can change the implementation later without breaking code others have
> written?

Don't change the interface.  Of course, if the implementation is changed 
in such a buggy way as to totally alter the behaviour, same interface 
doesn't mean jack.

>> It's all about scope.  If it's public, it should be used.  If it's not, 
>> you shouldn't.
> 
>   And what's wrong with the compiler telling you if you try to use it
> regardless? I really can't understand that.

Nothing wrong except quite a few more tiresome and bureaucratic measures 
before actually writing anything.

>   The compiler is not limiting anything that you aren't *already* limiting
> by your verbal agreement. The only thing the compiler is doing is checking
> that the agreement is not broken. Why that is a bad thing is beyond my
> comprehension.

I was not saying that is bad.  I was just reacting to this:  "Your 
definition of object-oriented programming may vary, but in my view
data hiding, ie. modularity, is an integral part of OO programming."

Modularity is still there regardless of dumb programmers ripping their 
contracts and no middleman to prevent them doing so.  But I'm thinking 
here on a typical Scheme module of old, before true modules, and where 
all you had was a list of functions and lexical scoping, not a C plain 
text file with lots of variables and variable-dependent functions lying 
all around.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:01:07
Message: <49c16113@news.povray.org>
Warp wrote:
>> Like, in unsafe languages, where a stray pointer can change private 
>> variables without going thru the class methods? :-)
> 
>   No. The reasoning behind data hiding in modular thinking is completely
> independent of the language used. It has to do with program design.

OK. I guess you look it as "if you bypass the documentation and access 
members not documented, I have to support your brokenness forever." I look 
at it as "if you're coding from the implementation instead of the 
documentation, you get what you deserve" combined with "don't make me debug 
my code when the bug is in your code."

>   If you expose the internal structure of a module to the outside, then
> there's a big chance that outside will start making *assumptions* about
> this internal structure.

Sure. Most of these languages (a) document what's public and what isn't, and 
(b) have a language-wide naming convention for it.  That is, after all, what 
C++'s 'private' tag is - a naming convention.

>   If this happens, then you can't change the internal implementation of
> this module without breaking existing code. For example, if you wanted
> to change the color components to floats, or you would want to pack the
> color components into one single integral value, you will most probably
> break existing code (especially probable in the latter case, as the
> amount and names of the member variables will change drastically).
> 
>   If you can design the absolutely perfect module which will never change
> its contents and will suffice for years to come, then by all means make
> all members public. Us mortals will try smarter techniques.
> 
>> C# and Java both have reflection that let you get to private members from 
>> outside.
> 
>   Thus it's one reason why the design of these languages is badly broken.

I think it's more a trade-off than you make it out to be.

>> C++ not only lets you return pointers to private members
> 
>   Only if the class itself explicitly does so. You can't get to the private
> members *from the outside*.

That's why I said it wasn't much of a breakage in my view.

> (Well, at least not without some serious hacking.)

Running off the end of an array is "serious hacking"? I wouldn't think so.

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

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

// My code
  xyz pdq;
  pdq.x[10] = 27;


>   You might be able to control your *own* code from not misusing public
> variables (and you might never make mistakes), but it's more difficult to
> control someone else.

Sure. See above examples.

>   If you need to tell someone else "don't access member variables whose
> name start with an underscore", that's just plain stupid. You should be
> able to tell that by making the *compiler* enforce it.

I agree, except for the fact that you're using C++ as an example. :) C++ has 
it's own different lack-of-modularity problems. If the compiler actually 
*enforces* that the member variables you declare private can only be changed 
by your own methods, that's great.

"don't access member variables whose name starts with an underscore" is the 
kind of rule that's enforced all through a codebase or a programming 
language. The little extra warning the compiler is going to give you is 
generally not of much benefit if someone's going to violate that rule 
anyway, IME.  In other words, if they really need to violate the privacy of 
your class, they're going to do it in C++ almost as easily as they do it in 
something like Python or LISP.  The compiler doesn't enforce the 
encapsulation in C++ - it just gives warnings when you use a variable name 
that's private. There's no enforcement at runtime, and plenty of back doors 
at compile time. Contrast with, say, C#, where you don't even know what the 
private variables are named, and you couldn't access them if you did, 
because the runtime enforces that - there, the only backdoor is the 
reflection libraries that specifically are bypassing the privacy checking 
system. Using reflection (or explicitly assigning to _private members) isn't 
any more common or more prone to abuse than ((int*)0x12345)=27; is, 
particularly because the user has to explicitly know they're violating 
encapsulation when they write the code.

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.

But there are a lot of people who don't want to write a ton of boilerplate 
code for a function that could be automated, so they're willing to say "if 
you use introspection  to read and write my structure over the wire, be 
aware it may change in other versions."  It's better to say "this will break 
with future versions" than to say "I'm going to write 5000 lines of 
boilerplate code to allow clients to send my values over the internet or 
into databases."

There are also a whole bunch of assumptions in your classes that someone is 
going to rely on that you're not going to be able to prevent. SimCity 
assumed memory you called free() on would still be valid until the next 
malloc(), which is obviously a bad assumption yet still has to be supported 
by the infrastructure if you expect to run simcity on later versions of the 
OS. If you store your object outside of memory or interact with any other 
objects, you're also going to have random dependencies created - someone is 
going to have to change database schemas to store your objects in a 
database, or change buffer sizes if you switch from JSON serializiation to 
XML serialization without otherwise changing your interface. There will be 
people who assume your class only invokes their getter method once, if 
that's how you first code it, and if you change to invoking it twice, they 
may very well fail out (because they're pulling the next row from a database 
for each invocation, say). Or, in short, you can't protect against bad 
programmers, and anyone half-decent isn't going to be frobbing private 
variables to start with, IME.

-- 
   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: 18 Mar 2009 17:01:24
Message: <49c16124@news.povray.org>
Rule #5:  Best documentation is the code. ;)


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:03:04
Message: <49c16188@news.povray.org>
Warp escreveu:
>   Not all member functions have to be public either. It's extremely common
> for a class to have private member functions which are part of its internal
> implementation and not even intended to be part of the public interface.

Exactly.  Lexical scoping takes care of that. For languages which allow 
conveniently-definable lambdas, that is.


Post a reply to this message

From: nemesis
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:05:18
Message: <49c1620e$1@news.povray.org>
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.


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:06:49
Message: <49c16269$1@news.povray.org>
Warp wrote:
> 1) I write "private:" once in my class definition.
> 
> 2) I write extensive documentation about the subject and hope people will
>    read it and obey it. Many people won't.

You missed this one:
   3) You name your private variables with the naming convention used by
      every other package ever implemented in that language, including
      the ones that define the runtime, and which every programmer knows
      bypassing means future incompatibility.

>   And what's wrong with the compiler telling you if you try to use it
> regardless? I really can't understand that.

You already know you're using a private variable, if you're bypassing either 
global naming conventions or using reflection or something.

If the compiler actually *prevents* it, then you're locking yourself out of 
a whole bunch of metaprogramming techniques that templates aren't adequate 
to handle.

-- 
   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 17:10:18
Message: <49c1633a@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> Certainly if should-be-private members are exposed as public but don't 
>> document to the user which are private, that's a problem.
> 
>   I thought you were old enough to know some basic facts of life:
> 
> Rule #1: People *don't* read documentation.
> Rule #2: Read rule #1.
> Rule #3: Even if people read documentation, they do not have photographic
>          memory and they forget.
> Rule #4: Humans are imperfect and make mistakes.

Sure. "Don't read documentation" or "forget documentation" is as bad as 
"don't document it". But if it's a naming convention used throughout the 
language, people don't do it.

How many people name their own function to add a list of numbers as
   __builtin_addlist()
in C or C++?  Why not?  Because everyone who is even a little knowlegable 
knows that two underscore names are reserved for the compiler.

>   Why is it a bad thing to make the compiler check interface breaches is
> beyond my comprehension.

First, the whole "dynamic languages" bit at the start should indicate not 
everyone has a compiler for these languages. Secondly, it eliminates a whole 
raft of useful mechanisms.  Where's the C++ library to which I pass a class 
and it generates a SOAP interface parser for that class?

-- 
   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 17:24:20
Message: <49c16684$1@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> You still get subclasses. And of course there's always the hack of declaring 
>> a subclass.
> 
>   A subclass can't access the private members of the base class.

Yeah, "protected" slipped my mind. It's still not hard to do if you're trying.

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

> If you are *intentionally*
> trying to break your program, then that's your choice, of course. However,
> in normal usage it's useful if the compiler checks that you don't make
> mistakes.

While I agree, I fail to see why using reflection as intended isn't "normal 
usage" and not "a mistake". It's not something you accidentally do. You know 
very well you're bypassing encapsulation. Not the least of which is that you 
need to give the name of the variable you want to access as a string.

>   Whether your program will link after that can depend on the compiler.
> It's certainly not standard-conforming. And again, you are hacking on
> purpose, trying to bypass the compiler checks, rather than using those
> checks to catch your mistakes.

Right. Since you said reflection violates encapsulation hard enough to make 
a program not "OO", I'm trying to figure out allowing type casts and 
assignment of arbitrary memory addresses to pointers doesn't.

Now, if the statement is "the compiler should be able to warn of external 
access to private variables, with the ability of the caller to easily 
indicate they know what they're doing," I'm 100% with you.

If the statement is "the compiler should error on external access to private 
variables, with no way to get around it," I'm 95% with you, with the caveat 
that "that's a pain in the ass way to write generic code that isn't type 
specific, because you have to write code generators instead of using the 
compiler you already have."

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

-- 
   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: 18 Mar 2009 17:25:38
Message: <49c166d2@news.povray.org>
nemesis <nam### [at] gmailcom> wrote:
> >   So in your opinion the concept of "interface" is a verbal agreement about
> > what should and shouldn't be used from a module? *That* is what sounds like
> > bureaucracy to me.

> Not bureaucracy at all.  Just a list of names of functions a module 
> provides.

  I really fail to see how that is different from using a *real* interface
specification, rather than just a verbal one. Except for the fact that with
a real interface the compiler can make sanity checks, of course.

> >> For people who know it better, the lack of such measure does not mean 
> >> irrestrict access to things, it simply means less stupid typing to make 
> >> the compiler happy.  Modularity is conserved.
> > 
> >   In Utopia, maybe. In the read world, not so.

> Indeed.  In real enterprise world we got people who don't enjoy nor know 
> how to program, programming.

  Yes, and these people put everything in the public part of their classes
because they don't have any idea what they are doing. In the same way as
those self-taught hackers who detest all programming paradigms.

> >   And I don't consider having to write "private:" once to be significantly
> > more typing.

> Indeed, Delphi and C++ are yet more zippy at that, not so much for those 
> poor Java souls... you also forgot the data type declarations.

  In fact, in C++ you don't even have to necessarily write "private:" at
all because members are by default private (when not inside any access
specifier block).

> > If I had to document what you should and should not access
> > in the module, *that* would be significantly more typing.

> This coming from a guy whose favorite language needs for one to provide 
> the source and the header file.

  What source?

> >   Also, if I make a module for others to use, how can I guarantee that
> > I can change the implementation later without breaking code others have
> > written?

> Don't change the interface.  Of course, if the implementation is changed 
> in such a buggy way as to totally alter the behaviour, same interface 
> doesn't mean jack.

  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.

> >> It's all about scope.  If it's public, it should be used.  If it's not, 
> >> you shouldn't.
> > 
> >   And what's wrong with the compiler telling you if you try to use it
> > regardless? I really can't understand that.

> Nothing wrong except quite a few more tiresome and bureaucratic measures 
> before actually writing anything.

  Thinking that brevity in programming is a good thing is a really common
beginner mistake. Those are the beginners who, for example, in C++ always
write "using namespace std;" to dump *everything* in the standard libraries
to global namespace because it saves them from typing 5 extra characters
later. Then you get code like this:

    i = search(first1, last1, first2, last2);

  "Woohoo! I saved typing 5 characters!" And now it's completely unclear
what this "search()" is. Is it a local function somewhere? Is it an external
function defined in some header? Perhaps it's a class which is being
instantiated? Is it a standard library function?

  Compare to:

    i = std::search(first1, last1, first2, last2);

  Now it's completely unambiguous that this is a standard library function
being called.

  Brevity is *not* always the answer. Even if I had to write "private" in
front of every single function and variable declaration (as you have to do
in some languages), I would still do it. (Fortunately I don't have to.)

> >   The compiler is not limiting anything that you aren't *already* limiting
> > by your verbal agreement. The only thing the compiler is doing is checking
> > that the agreement is not broken. Why that is a bad thing is beyond my
> > comprehension.

> I was not saying that is bad.  I was just reacting to this:  "Your 
> definition of object-oriented programming may vary, but in my view
> data hiding, ie. modularity, is an integral part of OO programming."

> Modularity is still there regardless of dumb programmers ripping their 
> contracts and no middleman to prevent them doing so.

  I disagree. There's no modularity if you can't enforce access rights.
Data hiding is an integral part of modular design. Verbal agreements are
worth absolutely nothing.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:28:55
Message: <49c16797@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Warp wrote:
> > 1) I write "private:" once in my class definition.
> > 
> > 2) I write extensive documentation about the subject and hope people will
> >    read it and obey it. Many people won't.

> You missed this one:
>    3) You name your private variables with the naming convention used by
>       every other package ever implemented in that language, including
>       the ones that define the runtime, and which every programmer knows
>       bypassing means future incompatibility.

  I still prefer option #1. It's not like it would exclude option #3, so
you get the best of both worlds: Clarity in naming conventions, *and* the
compiler checking the integrity of the interface.

> >   And what's wrong with the compiler telling you if you try to use it
> > regardless? I really can't understand that.

> You already know you're using a private variable, if you're bypassing either 
> global naming conventions or using reflection or something.

> If the compiler actually *prevents* it, then you're locking yourself out of 
> a whole bunch of metaprogramming techniques that templates aren't adequate 
> to handle.

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

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:29:53
Message: <49c167d0@news.povray.org>
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.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:32:30
Message: <49c1686e@news.povray.org>
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.
(Except when your code breaks when you update the library.)

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:42:23
Message: <49c16abf$1@news.povray.org>
Warp wrote:
>   I really fail to see how that is different from using a *real* interface
> specification, rather than just a verbal one. 

It's not "verbal". It's expressed in the code. It just so happens that 
there's a way to bypass it.  You say "My module exports the functions alpha, 
beta, and gamma."  You then later define alpha, beta, gamma, and delta. The 
caller can't get to delta without explicitly saying "hey, you know that 
private function delta in that module? Import it into my module."

It's not something you do by mistake.

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

And then someone comes and says "Gee, parsing this function each time is 
adding too much overhead. We need to store that structure in a database. And 
then we need to calculate it at the server and then ship the bytecodes to 
each client."   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. Or you 
pick the source up, and maintain it yourself in the future, which is just a 
special case of #2 there.

>   Brevity is *not* always the answer. 

You should try Ada!  ;-)

In any case, that sort of import is exactly the sort of way you bypass the 
access restrictions on exported functions in Python, for example. You have 
to go read the source (to find the name), then explicitly copy the function 
into your own namespace to invoke it.

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

WarpsClass x(...);
memset(&x,0,23);

If you think that's somehow unfair, then how is reflection any less fair?

-- 
   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: 18 Mar 2009 17:50:03
Message: <49c16c8b@news.povray.org>
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 could just invent a completely wild answer to that argument of yours as
well: "But loops use loop variables without the need of any hacking." It
makes exactly as much sense to me.

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

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

> >   If you need to tell someone else "don't access member variables whose
> > name start with an underscore", that's just plain stupid. You should be
> > able to tell that by making the *compiler* enforce it.

> I agree, except for the fact that you're using C++ as an example. :) C++ has 
> it's own different lack-of-modularity problems. If the compiler actually 
> *enforces* that the member variables you declare private can only be changed 
> by your own methods, that's great.

  It enforces it as long as you don't deliberately try to 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.

> In other words, if they really need to violate the privacy of 
> your class, they're going to do it in C++ almost as easily as they do it in 
> something like Python or LISP.

  Haha.

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

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

> There are also a whole bunch of assumptions in your classes that someone is 
> going to rely on that you're not going to be able to prevent. SimCity 
> assumed memory you called free() on would still be valid until the next 
> malloc(), which is obviously a bad assumption yet still has to be supported 
> by the infrastructure if you expect to run simcity on later versions of the 
> OS.

  I don't see any connection between that and the current subject.

> Or, in short, you can't protect against bad programmers

  So let's deliberately make bad code?

  That's exactly as silly as saying that it's useless to lock your car
because someone could break its windows anyways.

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 17:58:14
Message: <49c16e76@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> > 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.

> And then someone comes and says "Gee, parsing this function each time is 
> adding too much overhead. We need to store that structure in a database. And 
> then we need to calculate it at the server and then ship the bytecodes to 
> each client."

  That's a hilariously bad example because in order to get the object from
the database you will have to make a database call, which will parse its
internal structures (perhaps even directly from disk), after which your
object will be constructed from this parsed data. I would be really surprised
if that's not an order of magnitude slower and resource-heavy than re-parsing
the function.

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

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

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

-- 
                                                          - Warp


Post a reply to this message

From: Warp
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 18:00:49
Message: <49c16f11@news.povray.org>
Darren New <dne### [at] sanrrcom> wrote:
> Sure. "Don't read documentation" or "forget documentation" is as bad as 
> "don't document it". But if it's a naming convention used throughout the 
> language, people don't do it.

  And if it's a language feature, people don't do it either, not even by
accident.

> >   Why is it a bad thing to make the compiler check interface breaches is
> > beyond my comprehension.

> First, the whole "dynamic languages" bit at the start should indicate not 
> everyone has a compiler for these languages. Secondly, it eliminates a whole 
> raft of useful mechanisms.  Where's the C++ library to which I pass a class 
> and it generates a SOAP interface parser for that class?

  And then you modify your class, and your pre-existing SOAP interface parser
breaks.

-- 
                                                          - Warp


Post a reply to this message

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

  Let's talk about *standard-conforming* C++.

> > If you are *intentionally*
> > trying to break your program, then that's your choice, of course. However,
> > in normal usage it's useful if the compiler checks that you don't make
> > mistakes.

> While I agree, I fail to see why using reflection as intended isn't "normal 
> usage" and not "a mistake". It's not something you accidentally do. You know 
> very well you're bypassing encapsulation. Not the least of which is that you 
> need to give the name of the variable you want to access as a string.

  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.

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

> >   Whether your program will link after that can depend on the compiler.
> > It's certainly not standard-conforming. And again, you are hacking on
> > purpose, trying to bypass the compiler checks, rather than using those
> > checks to catch your mistakes.

> Right. Since you said reflection violates encapsulation hard enough to make 
> a program not "OO", I'm trying to figure out allowing type casts and 
> assignment of arbitrary memory addresses to pointers doesn't.

  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, you might as
well not use classes at all. What's the point?

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

-- 
                                                          - Warp


Post a reply to this message

From: Darren New
Subject: Re: This is the sort of brokenness...
Date: 18 Mar 2009 18:15:37
Message: <49c17289@news.povray.org>
Warp wrote:
> Darren New <dne### [at] sanrrcom> wrote:
>> Warp wrote:
>>> 1) I write "private:" once in my class definition.
>>>
>>> 2) I write extensive documentation about the subject and hope people will
>>>    read it and obey it. Many people won't.
> 
>> You missed this one:
>>    3) You name your private variables with the naming convention used by
>>       every other package ever implemented in that language, including
>>       the ones that define the runtime, and which every programmer knows
>>       bypassing means future incompatibility.
> 
>   I still prefer option #1. It's not like it would exclude option #3, so
> you get the best of both worlds: Clarity in naming conventions, *and* the
> compiler checking the integrity of the interface.

I disagree. Now you've got a naming convention that isn't enforced that 
would mean something to people trying to read your code. Duplicate work, 
with uglier source code, and insufficient reliability to depend on. I think 
we've all learned that faux-Hungarian notation is a bad idea.

Unless the compiler also enforces that (say) privately scoped variables 
start with an underline, at which point, why? What prefixes are you going to 
have the compiler enforce, and what benefit does it bring, and why not just 
have the prefix indicate the type information (like trailing $ means string 
in basic)?

>> If the compiler actually *prevents* it, then you're locking yourself out of 
>> a whole bunch of metaprogramming techniques that templates aren't adequate 
>> to handle.
> 
>   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).

Not really. The beauty of the reflection libraries are that they allow the 
person using them to *adjust* what they do when you change your code, all 
without having to change *their* code.  Does using
    write(handle, &thestructure, sizeof(thestructure))
prevent you from ever adding anything to thestructure? No. Why? Because 
you're getting metadata from the compiler (via sizeof) rather than 
hardcoding a 137 as the size or some such.

Of course, that's hardcoded at compile-time, and the results it writes out 
can't be read into an instance of the new version of the structure, which is 
exactly why people started building more complex reflection libraries, 
hibernation libraries, and so on.

If you have something like your function parse library, and I want to take 
an instance of that and send it to a process on a different machine, how do 
I do that?  I can't, without violating the encapsulation, because you didn't 
provide for that.  But if my income this week depends on me getting to your 
private variables, C++ isn't going to be able to stop me.

(I may be wrong, but it doesn't look like you provide accessors for anything 
in the instance, so I can't even look at it after the fact and see what 
function it's representing? It looks like I can't have a function that takes 
an instance of FunctionParser and pulls out enough information that I can 
make a second FunctionParser that does the same thing, other than via 
AddFunction (second overload)?)

But with reflection, I can write code that does this, *and* it will *still 
work* even after you change your class, even if you rewrite it completely.

Hacking past "private" is a whole different ball of wax than reflection. 
Hacking around "private" can be a mistake (bad pointer) or intentional 
(#define private public), but reflection is always intentional *and* it's 
easy to write it to self-adjust.

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

Goto Latest 50 Messages Next 50 Messages >>>

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