Re: Read-only, as opposed to const member
From: Howard (alicebt_at_hotmail.com)
Date: 06/25/04
- Next message: Andre Kostur: "Re: Clarity"
- Previous message: CFG: "Re: bitcounting on 30000+ bits, but not byte aligned"
- In reply to: Julie: "Re: Read-only, as opposed to const member"
- Next in thread: JKop: "Re: Read-only, as opposed to const member"
- Reply: JKop: "Re: Read-only, as opposed to const member"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Date: Fri, 25 Jun 2004 14:26:27 GMT
"Julie" <julie@nospam.com> wrote in message
news:40DBB1F4.A050C022@nospam.com...
> Howard wrote:
> >
> > "Julie" <julie@nospam.com> wrote in message
> > news:40DB0AA6.F2B5BDED@nospam.com...
> > > Richard Herring wrote:
> > > > What happens if you move to a more sophisticated colour model?
Instead
> > > > of storing an int, maybe you need to compute something from the
user's
> > > > choice, the available palette, the kind of display device etc...
> > >
> > > No, you create a new or derived class.
> > >
> >
> > But then you break everyone's code that uses your original object! They
now
> > have to change their code to use your new object, whereas if you just
> > returned the computed value from the accessor, the user of your class
never
> > even has to know how that value was computed, how it was stored, or
> > anything. They never even know the underlying accessor code was changed
at
> > all. They get the value they want when they ask for it, and that's all
they
> > should care about.
>
> ??? Explain to me how you _break_ existing code by creating a new or
derived
> class. In every scenario that I've been involved in, creating a
new/derived
> class broke nothing -- and those that wanted the extended/different
behavior
> provided by the new class, modified their code.
>
Below, I did explain. As I said, my system was used by thousands across the
country, and if there was any back-end database change or access method
change, I was in general *required* to implement without changing the public
interfaces. This has nothing to do with providing some neat new toy they
can play with, but changing the way our classes do their work internally,
which is none of the user's business.
Sure, I had performance requirements to accomodate, but those drove how I
internally did my work. If it takes a month to propogate interface changes
out to the users, what good is that if it saves a few milliseconds of
functon call time? I had to make changes to the back end fairly frequently
(some of them required by the federal gov't), and there's no way we could
send out a whole round of software to the uers every time we changed how we
stored or accessed our data.
> Maybe they _should_ know that the accessor has changed, perhaps in subtle
ways
> that the modifying author didn't foresee...
>
> > Experience has taught me this well. In writing database-access
programs, I
> > often had to change something on the back end, and I was in general
> > *required* to not change the interface. When the user wants the trip
> > mileage, they never need to know if that was a stored value, or if it
was
> > computed via a third-party mileage lookup. WIth thousands of users of
our
> > system spread across the country, it was *very* important to make these
kind
> > of changes as invisible to the users as possible. (It often took at
least a
> > month to propogate changes to users when we had to make an interface
change,
> > and we had to in effect maintain two system during such
transitions...what a
> > pain!)
>
> Sure, there are many (most!) cases where a functional-based accessor is
the
> appropriate implementation -- but I'm not limiting myself to saying that
it is
> the _only_ way to implement accessors.
>
Ok, but your statement that started me off responding here was "No, you
create a new or derived class." And I'm suggesting that's not the common
way to change your internal implementation. The whole point of
encapsulation is that the internal workings are private, and not the
business of anyone using the object (unless otherwise specified explicitly,
such as specific side-effects).
> > > > OK, add some functionality to compute it:
> > > >
> > > > private:
> > > > int ComputeComplicatedColour(int userColour, palette p, display d)
> > > > const;
> > > >
> > > > If returning a value, no problem; just change your access function
to
> > > > this:
> > > > int GetColour() const
> > > > { return ComputeComplicatedColour(colour, palette, device); }
> > >
> > > You have now just changed the behavior of the original function with
> > respect to
> > > performance, which is a very real and tangible change.
> > >
> >
> > Only in the internal behavior of the object, not in the interface or the
> > contract to provide the requested value.
>
> That is correct, but you are presuming that the only imposed requirements
are
> for the interface and returned value. There are other characteristics
that
> must be taken into account when implementing a public function, and one of
> those are performance characteristics.
>
Sure, but that's a separate specification, not part of the contract provided
by the function interface. And in the case of something simple like
computing a color from some values, how much of a hit are we talking?
COmpare that to the month it took me to distribute code changes to the
users!
> > > This is why I advocate const reference member accessors to simple
data --
> > it
> > > *guarantees* that access to the underlying data is immediate and
absolute,
> > and
> > > will stay that way. It doesn't break encapsulation as some have said,
but
> > > creates an immutable contract between the class designer and class
user.
> > You
> > > can't get that w/ functions.
> >
> > I don't understand this. Why is a guarantee to "immediate and absolute"
> > access to the underlying data a requirement? What does the user of the
> > class care how the data is stored, represented, obtained or calculated?
The
> > contract is to provide the value asked for, not (in general) a
specification
> > of how that value is obtained or stored.
>
> "Immediate and absolute" access is only a requirement if necessary, hardly
an
> absolute for all (most?) implementations.
>
> In most cases, the user will not care how the data is stored, but they may
care
> how the data is accessed *or* computed.
>
> Here is a simple example: suppose you are using a string class that
implements
> the length as a function (string::length()). Now, when iterating over
that
> string in a for-loop, they need to decide on:
>
> size_t length = str.length();
> for (int index=0; index<length; index++) // etc.
>
> -- or --
>
> for (int index=0; index<str.length(); index++) // etc.
>
> If the implementation details of length() is unknown, they have to resort
to
> the first.
>
> However, if the length is exposed as a public data reference, then it can
be
> guaranteed that str.length is immediate access and results in:
>
> class string
> {
> public:
> const size_t & length;
> // etc.
> };
>
> for (int index=0; index<str.length; index++) // etc.
>
Profiling can tell you if performance is suffering, and some published
knowledge about internals can indeed tell you if you can do something
better. But if you're *depending* upon the internal implementation details
of a class you use in order to design how you use the class, then you most
definitely *are* breaking encapsulation. That's exactly what encapsulation
is about, keeping those internals private. (Look at most third-party
libraries...you get a .dll or .lib or some other binary of the actual
implementation code, and only header files as source code. They don't
*want* you to know their internal workings! It's probably copyrighted, for
that matter.)
> Finally, I'm not advocating this idiom in any particular case, just saying
that
> in the given situation, it may be appropriate and suitable. If you happen
to
> disagree, that is perfectly fine with me, I'm not trying to convince you
> otherwise, I'm just leaving my coding options open.
Ok, I can understand that. It's a "good thing" to look carefully at the
specific problem at hand before making decisions as to how to solve it.
But I still say it's better, in general, for accessors to return by value
than by reference. (And I also agree with others that, even in the specific
case given, it's better, because it's always possible that the object that
returned the reference could be destroyed while the calling code still
wanted to use that value.)
-Howard
- Next message: Andre Kostur: "Re: Clarity"
- Previous message: CFG: "Re: bitcounting on 30000+ bits, but not byte aligned"
- In reply to: Julie: "Re: Read-only, as opposed to const member"
- Next in thread: JKop: "Re: Read-only, as opposed to const member"
- Reply: JKop: "Re: Read-only, as opposed to const member"
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Relevant Pages
|