|
![](/i/fill.gif) |
Darren New <dne### [at] san rr com> wrote:
> 1) They're enforced 100%. Nobody outside the class is capable of writing to
> or reading from a private variable. This provides maximum isolation at the
> expense of not having available at runtime lots of stuff the compiler knows
> at compile time that you might want to know (e.g., reflection type stuff).
If you need to know the private members of the class from the outside,
then that class has been badly designed.
With a well-designed class you don't *need* to know, nor care.
> 2) They're enforced 100%, but people outside the class can read but not
> write them. This is a little more fragile to change
It breaks modularity badly. The whole idea of data hiding is that the
private part should be completely opaque to the outside. The second it
isn't, outside code will start making assumptions, and you can't change
the implementation of the class anymore.
> but still capable of
> being debugged in isolation, because other parts of the code can't break
> your invariants. Eiffel does this, but it's the same syntax (x.y) to
> reference the y member of x as it is to invoke the nullary member function y
> on x, so you don't need to do more than recompile the client code. (I think
> you can also say a variable is completely private, IIRC.)
Some people argue that accessors to all private members, especially if
they are automatically generated, is almost as bad as having all the
members public. It exposes the internal implementation, and thus outside
code will start making assumptions about it, making it harder to change
the implementation later.
Some accessors may be justifiable, but you should not go overboard.
> 3) They're enforced, but there are explicit mechanisms to bypass them, such
> as reflection. This is my personal preference, because it's easy to find the
> places in the code that might be breaking your invariants or might rely on
> your internal implementation, while providing the power of metadata. This is
> the C# and Java model.
If you don't have access to the code which is making assumptions about
your class' internal structure, you can't change your class without breaking
that existing code.
Sure, this situation might not be extremely common, but it can happen.
And it's something which might have been avoided with a good interface
design and a completely opaque private implementation.
> 4) They're enforced by the compiler but not by the runtime. This removes
> *both* the ability to debug your module in isolation *and* the ability to do
> metaprogramming that eliminates boilerplate by using the information the
> compiler has already calculated.
Why would you want runtime checks if access rights could be fully checked
at compile time?
> 5) They're not enforced by the compiler or the runtime, but there are
> conventions and/or standards that make it obvious to everyone when you're
> breaking the data encapsulation, and the runtime ensures that you can only
> do this "on purpose". That is, the unenforced conventions (or enforced but
> bypassable mechanisms) ensure that the only way of breaking encapsulation is
> on purpose. This is almost as good as #3, except it may be harder to track
> down who is violating your invariants.
Again, if you must keep "reverse compatibility", for a lack of a better
term (in other words, you as a library developer must maintain compatibility
with existing code which uses your library, and you don't have access to
this existing code nor can change it), it can be a problem if the existing
code can make assumptions about your library and does so.
> > I think that your problem is that you have some kind of holy war against
> > C++, and every single discussion about programming is always somehow turned
> > to bashing C++.
> Nope. Someone brought up C++ by talking about the compiler enforcing
> "private:". I was just pointing out that the compiler only enforces it in
> some ways, and not in the ways that I thought was also important for modularity.
You immediately assumed that it must be talking about C++, of course,
and immediately jumped at the opportunity of bashing it.
> > I'm honestly getting tired of your C++ tirades. Every single subject
> > related to programming must somehow include C++ bashing, regardless of
> > the subject. That's getting tiresome.
> I'm really not trying to bash C++ here. If pointing out that C++ allows you
> to corrupt member variables with a bug is "bashing", then I guess I'm bashing.
In a discussion about the modular programming paradigm and data hiding you
succeeded in creating an lengthy thread about how you can trash memory in C++.
It's not exactly like you avoided the subject.
> OK. I'm just trying to communicate here. That's why I'm asking the question.
> It seemed to me that you preferred a language with unsafe behavior and
> compiler-enforced checks to one with safe behavior and no compiler-enforced
> checks.
That "you preferred a language with unsafe behavior" is 100% your own
invention. I have nowhere said that.
What I have said is that I prefer enforced modularity over non-enforced
one (which IMO is not modularity at all). That "unsafe" bit is all your
own twisting.
> I've never heard you call C++ a kludge OO language. I assumed you were
> excluding C++ from that criticism when you said a language that allows
> access to private members is a kludge OO.
At least you admit you are making assumptions.
--
- Warp
Post a reply to this message
|
![](/i/fill.gif) |