|
|
Warp wrote:
> "Data hiding" doesn't mean "hidden from the programmer", but "hidden from
> the outside scope".
Fair enough. If that's how you want to look at it.
The way I see it is that encapsulation is a mechanism to reduce the area you
have to look to understand or use or debug a particular part of a program.
It makes things modular. The less modular changes are, the less encapsulated
the changes are.
If you can't see or access the private variables at all, that's extremely
encapsulated. If you can see and access them only through reflection or
explicitly-declared unsafe operations, that's less encapsulated. If you need
to see them because changes in private parts mean you have to deal with it
in your own code (say, by recompiling or changing the size of structure
declarations), that's also less encapsulated. When a bug in one part of the
program can cause arbitrary changes elsewhere, that's really minor
encapsulation.
I find "the compiler tells you if you explicitly write code that tries to
access stuff you can see but is flagged private" as the weakest form of
encapsulation out there, in terms of "information hiding". Only something
like Python that doesn't even try is weaker than that.
> In other words, code out of the scope of the class has
> no direct access to the internals of the class
And you understand why I'm disputing that this is the case, right?
*Correct* code has no direct access to the internals of the class *by name.*
Incorrect code has direct access to the internals of the class, and correct
code has direct access as long as it doesn't do so by name. (For example,
write(outfile, &myInstance, sizeof myInstance);
> You could as well argue that if you had an open source library in a language
> with true data hiding (by your definition of the term), it stops being data
> hiding because the programmer could just look at the source code of the
> library and see the internal structure of the objects. Just because the
> programmer can see the internal structure of the object doesn't stop it
> from being data hiding.
No. I'm not talking about just the programmer.
> The purpose of encapsulation and data hiding is not to obscure information
> from the programmer, but to offer an abstraction tool for the program design.
That's one of many purposes. I think the primary purpose is not to say "this
is public and that is private", which could be done as easily by a naming
convention or comments, but to also allow for debugging, understanding,
production pipelines, etc.
This abstraction is the only encapsulation that C++ provides, so naturally
that's what you think the purpose of encapsulation is. But there's a whole
bunch of reasons for encapsulation. Plus, these additional forms of
encapsulation have all kinds of other benefits, which is why (for example)
you don't see applets written in C++.
> (In that way "data hiding" is perhaps slightly a misnomer, and something like
> "scope access restrictions" would be better.)
Now who is changing definitions? :-)
> In other words, if you want to keep a good abstraction level in your
> program, if something is marked as "private" then that something doesn't
> interest you unless you are actually implementing the class which owns
> that private member.
And in Python, if a variable name starts with _ then that variable doesn't
interest you. Does that mean Python has encapsulation like C++ does?
In languages where the private variables aren't exposed at all, this
question doesn't even come up. So C++ (and Ada, and the other languages that
increase efficiency by exposing the private declarations to client code)
isn't even very good at this. You wouldn't even *need* a "private"
declaration in the header file but for that. It wouldn't be a case of "the
compiler tells me that's private" as much as "the compiler tells me that's
not a member of the class."
>> All unsafe languages fail this. (Lots of safe languages do too, with
>> appropriate declarations of their unsafeness.)
>
> Now you are deliberately confusing a general non-restriction of memory
> access with the concept of data hiding.
No. You're confusing data hiding with encapsulation. You've changed the
subject from "encapsulation" to "data hiding", because data hiding is the
*only* kind of encapsulation C++ supports.
If you asked me if C++ supports data hiding, I would have said "Yes, poorly,
because you can see what's there and have to deal with it, but the compiler
enforces the private keyword."
I told you why encapsulation is important, listing several reasons. Data
hiding is just one of them.
> Again, data hiding is a tool offered by the language which you can use
> to increase abstraction in your program. Just because the language doesn't
> guarantee that modification of random memory locations using wild pointers
> will always be caught doesn't make the tool nonexistent. The tool is still
> there for you to use, and the compiler will enforce it as long as you write
> your code as intended.
That's correct. But that's not all that encapsulation encompasses. "Data
hiding" is not the only thing that encapsulation provides.
>
>> """
>> Hiding the internals of the object protects its integrity by preventing
>> users from setting the internal data of the component into an invalid or
>> inconsistent state.
>> """
>
>> Unsafe languages fail at this. Either that, or you have never ever
>> encountered a wild-pointer bug.
>
> A wild pointer bug is at a completely different conceptual level than
> data hiding.
Yep. Not the point tho. It's at a different conceptual level, which is
exactly *why* it is so hard to debug. You can't look at the assignments to
the variable and figure out which one might have set the denominator of your
Fraction class to zero.
Look, I'm just going thru the definition *you* pointed me at and showing
that unsafe languages don't meet the definition.
You don't need to hide the internal variables to prevent someone from
setting them to an invalid state. For example, Eiffel has clauses in the
source code that describe the valid states of internal variables, so you
could in theory check at each assignment that nobody outside the class is
breaking the internal consistency.
The only way in which hiding data prevents the consistency from being
corrupted is if it's actually inaccessible when it is hidden. Unsafe
languages fail at that. You can clobber and make inconsistent data that is
hidden at the "conceptual level" of the language.
> Encapsulation exists as a tool for *programming*, not as a
> tool for the runtime.
I disagree. Considering what the compiler does without considering what the
runtime does says little about your language. You're the one that says C++
is superior to Java because of the runtime.
Runtime encapsulation is what made Java popular in the first place. Indeed,
runtime encapsulation was pretty much the entire point of Java's development.
> If you use encapsulation as intended, and your
> program is correct, then the compiler will enforce the encapsulation.
I already granted that "if your program is correct" then C++ has a minimal
level of encapsulation. That's not really saying much, tho. "If your program
is correct" in Python, you don't screw with publicly-accessible members that
aren't documented. That doesn't mean Python has as good encapsulation as
C++ does.
> I think that your problem is that you somehow write like having bugs
> in your program is some kind of valid programming technique.
No. I write like someone who codes against libraries built by people who
aren't as good a programmer as I am. We're long past the point in computers
where people run "their program" in an environment where every bug is
guaranteed to be their own.
Heck, even *with* the runtime encapsulation that Javascript enjoys, people
*still* run separate tabs in separate processes.
> "Encapsulation
> should be enforced even if there are bugs in your program" sounds quite
> silly.
Tell that to people running Java applets in their web browser. I mean, isn't
that basically the difference between Java applets and ActiveX?
> It kind of implies that "your program should still run ok even if
> there are bugs in it".
You know something? There's an awful lot of software that falls into this
category. Know why? Because programmers aren't perfect.
> Assume that you have a bug in your program in that you forgot to write
> "private" in conjunction with a member declaration, making it public.
> There's a bug in your program, which made the member accessible from the
> outside. By your definition this programming language doesn't enforce
> encapsulation because if there are bugs in your program it may allow
> private members to be accessible from the outside.
Not at all. The difference is that when I go to my class where the problem
manifests as incorrect data in instance variables, and I look through the
code that references those ought-to-be-private variables and see that none
of them set it wrong, and then I look at the declaration and see it's
public, I can change that to private and see who is accessing it that
shouldn't.
On the other hand, when you have a wild pointer bug overwrite my instance
variable, the place I have to look in the code to find that is *everywhere.*
Including code I don't have source for.
You're either trolling me, or you're a really crappy and/or inexperienced
programmer if you don't understand the difference between the scale of
looking for a bug in those two places. The whole *point* of encapsulation is
not to serve as documentation as to what's public and what's private, but to
limit the amount of code you have to look at to understand the behavior of a
given variable.
> That's just silly. You cannot define the concept of encapsulation in
> terms of buggy programming.
Yes! You can! That's exactly the point. You're encapsulating who can change
what values, so it's easy to find.
That's like saying "You cannot define the concept of structured programming
based on not executing gotos to arbitrary locations, because if you're
careful with your gotos, it's the same code as structured programming."
Sure, that's exactly what it is, because you're *guaranteeing* that the
structure is there. You don't have to check every goto to make sure it's
only a goto from the end of "then" to the end of "else" or some such.
>> That is, pretty much, the difference between safe languages
>> and unsafe languages: Safe languages *enforce* encapsulation.
>
> No, they don't. If you make a programming error and inadvertedly make
> a member public, the compiler will do squat about that.
True, but now you're asking the compiler to detect errors in *correct*
programs, which is orders of magnitude harder than asking the compiler to
detect errors in incorrect programs. There are very few compilers that will
detect that the program doesn't match the spec, altho LOTOS and Eiffel both try.
> You are deliberately confusing a programming technique such as
> encapsulation with a runtime technique such as memory protection.
Not really. Indeed, when taken to extremes, encapsulation enforces safe
language features. By using a "safe pointer" in C++, you've encapsulated the
operations on the pointer and ensure you don't do something like access it
after it's disposed. By using a "container" instead of just an array, you've
encapsulated access to the container's elements and can enforce that you
don't go out of bounds or throw an exception if you change it during
iteration or some such.
--
Darren New, San Diego CA, USA (PST)
The question in today's corporate environment is not
so much "what color is your parachute?" as it is
"what color is your nose?"
Post a reply to this message
|
|