Non private privacy

Started by
68 comments, last by Emmanuel Deloget 17 years, 10 months ago
Quote:Original post by Kest
Don't get me wrong. I completely understand the reasons to use Get/Set and private members. But I'm saying there are times when I know the data is safe to do anything with, such as a generic bool value. How badly screwed can a program become because of the value of a bool member?


Encapsulation isnt just to enforce variants.
The client code which uses the classes that you write should be unable to use your class in the wrong way. 'What' your class does should be strongly seperated from 'how' it will do it. If you are fiddling with a classes data you are working with the 'how', not with the 'what'.

Look at the STL - 'what' it does is clearly defined standard, but every different C++ compiler has a different implementation of how it will do it. Your classes should be the same; if you decide to change the implementation, it should have no effect on the clients. If the clients have their fingers in your private data though, then changing the implementation will break the client code.

If you've decided in the design of a class that there is a boolean that should be able to be changed at any time to indicate a certain state, you could make it public, but then if at a later stage you decide you want to pack those 30 booleans into a single integer, you have to go and update every bit of code that uses the boolean. Whereas if you used a function, like:
void SetMyState( bool b ) { m_bMyState = b; }
Then it can easily be changed to:
void SetMyState( bool b ) { b ? m_iFlags |= MY_STATE : m_iFlags &= ~MY_STATE; }


Anyone who writes professional C++ code MUST read Scott Meyers "Effective C++"
Advertisement
I already demonstrated why that argument is false. It's trivial to make that change without affecting client code.
Quote:Original post by Deyja
Quote:Looks like that's just more work. What is the advantage?

I was being facetious. What you can take from that example is that it's easy to retrofit code later without changing the callers. As for the gui example; I'd just have a public color member.

I'm asking what the advantage of using the templated public rerouter is over using simple inlined Get and Set functions. You have to write more code and the member variable name is far less "objectized" than Set..Something. I thought the whole point of avoiding Set..functions was to make the interface seem more like the speed controls to a spaceship rather than the wiring to it's engine. Doesn't a member variable, even if routed to private and safetized, go in the exact opposite direction?

edit: It took a while, but I see what you were doing. Showing those who were complaining about public members that you could change implementation later on. Still, I think I would prefer a Set/Get combo rather than this type of thing.

Quote:For the keyboard example, a more appropriate function would be 'bool is_key_pressed(keycode)'.

Now it just sounds like you're avoiding the words themselves. I could write all of my functions in Japanese, but I doubt it will help my design. Giving out the states of it's keys is exactly why the keyboard object would exist at all. So having GetKey or something similar is exactly what you would want. Unless of course you have is_key_down along with is_key_pressed, because then I would agree with you. But if you're just avoiding the Get word, I don't follow your allergic reactions.
Quote:Original post by Kest
Quote:Original post by Deyja
At any rate, I NEVER write get or set in a function name.

Just avoiding the name doesn't really accomplish anything, does it?


Sure it does. If you're using get/set, it's a pretty typical indicator you're thinking about setting/getting the member variables, rather than performing operations on the object as a logical whole. By avoiding keywords of the "member access" frame of mind, you're more likely to use the "object actions" frame of mind, thus (hopefully) leading towards better encapsulation.
Quote:Original post by MaulingMonkey
Quote:Original post by Kest
Quote:Original post by Deyja
At any rate, I NEVER write get or set in a function name.

Just avoiding the name doesn't really accomplish anything, does it?


Sure it does. If you're using get/set, it's a pretty typical indicator you're thinking about setting/getting the member variables, rather than performing operations on the object as a logical whole. By avoiding keywords of the "member access" frame of mind, you're more likely to use the "object actions" frame of mind, thus (hopefully) leading towards better encapsulation.

I suppose, if you're trying to use psychology to counteract your own bad habits. In a lot of cases, something other than Get works better. But sometimes, Getting is exactly what you're doing.

Here's one for you guys.

const MATRIX& RenderObject::GetTransform() const;
Quote:Original post by Deyja
I already demonstrated why that argument is false. It's trivial to make that change without affecting client code.


I'd hardly say that using advanced template techniques to disguise one thing as another is trivial.

So for the sake of clean designs and readable code I'd say you proved there are alternatives, but not that it is false.

BTW, read effective C++
Quote:Original post by Kest
Here's one for you guys.

const MATRIX& RenderObject::GetTransform() const;


I'd prefer Transformation() and ChangeTransformation() (and/or Rotate(), Move(), Scale(), etc). This is also more in line with the SC++L - e.g. size() and resize() (and/or push_back, insert, etc)

Psycology can be used to reinforce good habits as well, and to avoid things which while not being habits, might accidentally slip in occasionally.
Quote:Original post by MaulingMonkey
Quote:Original post by Kest
Here's one for you guys.

const MATRIX& RenderObject::GetTransform() const;


I'd prefer Transformation() and ChangeTransformation() (and/or Rotate(), Move(), Scale(), etc). This is also more in line with the SC++L - e.g. size() and resize() (and/or push_back, insert, etc)

Psycology can be used to reinforce good habits as well, and to avoid things which while not being habits, might accidentally slip in occasionally.

You're saying you would name a function that is supposed to obtain the transformation matrix of an object "Transformation()"?
Its good to make accessor methods so you dont accidently change member variables them. Just good practice.
Quote:Original post by Kest
Quote:Original post by MaulingMonkey
Psycology can be used to reinforce good habits as well, and to avoid things which while not being habits, might accidentally slip in occasionally.

You're saying you would name a function that is supposed to obtain the transformation matrix of an object "Transformation()"?


Probably - it's a property of the class. Part of the interface. "ChangeTransformation" is much more up for grabs - I'd more likely go for actions which don't completely overwrite the original contents. Rotate( dangle ) instead of SetRotation( absolute_angle ), Transform( matrix_to_transform_current_matrix_by ) instead of SetTransformation( absolute_matrix_to_overwrite_the_existing_with ).

This topic is closed to new replies.

Advertisement