What is this called? And is it a good idea?

Started by
36 comments, last by Shannon Barber 18 years, 3 months ago
Quote:Original post by Conner McCloud
We can bicker about this all day, but that doesn't address the OP in the slightest. What are people's thoughts on the BBBs scheme?

CM


It's too much extra work for crippled emulation of properties.

[Edited by - wild_pointer on December 30, 2005 10:45:21 AM]
[size=2]
Advertisement
emulation of properties that doesn't emulate properties. Because he can not make these properties do anything useful like (for example) update something else on set.

As in
...void SetSelection(int a){ if(a==m_selected)return; if(m_selected>=0)m_items[m_selected].UnSelect(); m_selected=a; if(m_selected>=0)m_items[m_selected].Select();}...int GetSelection(){ DEBUG_BLOCK( if(m_selected>=0)MY_ASSERT(m_items[m_selected].Selected()); ) return m_selected;}

All useful examples of setters is like that - do something when setting and/or getting.
The OP's thing can not do it, that's why it is useless.

and why not make getters and setters in advance if code doesn't do things like that: IMO if you have m_selected and want to add such additional functionality that were previously absent, it's better if you had it as public and move to private so code will not just compile and you get forced review and chance to catch possible problems caused by sideeffects. If you had get and set that were simply modifying m_selected, your code will compile instantly after modification, but with large chance code will be assuming that get and set are not doing anything extra so when get and set begin to do something extra it will break in strange ways.
Of course that is kinda different for libraries used by other people.

[Edited by - Dmytry on December 30, 2005 10:52:25 AM]
Quote:Original post by Dmytry
emulation of properties that doesn't emulate properties. Because he can not make these properties do anything useful like (for example) update something else on set.


I didn't look very closely or think it through very well but you could conceivably derive from SSGEntity and overload get and set and have some subset of the abilities of properties but yeah, you're right, it sucks.

Quote:Original post by Conner McCloud
Changing your internal representation to int or float or a bit vector all fundementally change the behavior of your class. All you've done by hiding them behind mutators is allow the resulting bugs to compile. Storing them as an array is rather pointless, and if need be it is possible to create public x,y,and z variables that reference the array anyhow .<br><!–QUOTE–></td></tr></table></BLOCKQUOTE><!–/QUOTE–><!–ENDQUOTE–><br><br>They're all admitedly stupid changes, I was just arguing accessors/mutators aren't completely pointless even when used trivially. I was &#111;nly thinking you could go from storing x, y, z as ints to floats and just cast in the accessors/mutators, same goes for bitvectors as long as long as it was big enough to store the same range of values.<br><br>Personally, I'm happy with my vectors being little more than POD types.
[size=2]
no, you're happy with thinking that your vectors are bit more than PODs . Whereas chances are you are either directly sending them to openGL or otherwise use direct access to specific memory layout, or your code copies all data when it needs to send it to anything and is inefficient for no reason.
Quote:Original post by Dmytry
no, you're happy with thinking that your vectors are bit more than PODs . Whereas chances are you are either directly sending them to openGL or otherwise use direct access to specific memory layout, or your code copies all data when it needs to send it to anything and is inefficient for no reason.


I think you misunderstood me. I was just admitting that my vector implementations do in fact use public member variables, it would be a POD type except I believe having a constructor exempts it.

Anyways, thanks for the discussion.
[size=2]
Quote:Original post by wild_pointer

Quote:Original post by rip-off
i never use get/set things by default. my classes mainly respond to commands. i have queries, but they rarely return the value of an actual variable inside the class( with the notable exception of bools ):

e.g. my current Image class's header file.
*** Source Snippet Removed ***


But now you have violated the one class, one responsibilty principle.


if you are referring to the static vector of loaded images and associtaed functions, they are there (*still, sigh*) because i need to reload all images when going to fullscreen/ not fullscreen. i have since moved this responsibility to my imageFactory class, but havent removed that part yet...

shocking how many people give stupid advises about setters/getters [rolleyes]
for one, they indeed hide the implementation, because sometimes you might calculate the get-value on the fly instead of straight accesing a variable, respectively spread the set-value over various values.
and even if you don't need that (read: your'e the 1337 hax0r and never change your ingenious design) accessors are the only way to implement save value-checks (assertions, exceptions...).

@what the starter tries to do: not a bad idea, but i'd at least extend it with some assertion mechanism, so one could easily create a checked value without much hassle. something one actually needs all the time - right? [caution]
------------------------------------------------------------Jawohl, Herr Oberst!
Quote:Original post by maximAL
shocking how many people give stupid advises about setters/getters [rolleyes]
for one, they indeed hide the implementation, because sometimes you might calculate the get-value on the fly instead of straight accesing a variable, respectively spread the set-value over various values.
and even if you don't need that (read: your'e the 1337 hax0r and never change your ingenious design) accessors are the only way to implement save value-checks (assertions, exceptions...).


template < typename scalar_t , scalar_t min , scalar_t max >class bounded_scalar {    scalar_t value;public:    typedef bounded_scalar< scalar_t , min , max > self_type;    self_type & operator=( scalar_t new_value ) {        assert( new_value >= min );        assert( new_value <= max );        value = new_value;        return *this;    }    ...};struct rgb_color {    bounded_scalar< double , 0.0 , 1.0 > red, green, blue;};


This is not an argument for or against public data (although I swing towards the extreme end of the "for it" camp). This is merely part of a limited example of delegating responsibility to a subclass in such a manner that any/all of the correctness checking responsibility of the owner is lifted, thus allowing our data to become public while still mantaining all the appropriate invariants (in this case, that 0.0 <= component <= 1.0).

BBB: 1) m_member m_prefixes m_are m_usually m_reserved m_for m_member m_variables m_rather m_than m_every m_function m_you m_can m_tack m_them m_onto. m_Also, m_it's m_pretty m_obvious m_they're m_members, m_just m_like m_it's m_obvious m_these m_are m_all m_words. m_In m_my m_opinion, m_anyways,

2) This approach has flaws the moment you need to check/modify something else in the class. You have two options:

a) Your syntax breaks:
foo.bar.set( 3 ); becomes foo.set_bar( 3 );

b) Your sub-member gets a pointer to foo (extra data):

class Bar {    Foo * parent;    int v;public:    Bar( Foo * parent ) : parent( parent ) {    }    void Set( int new_v ) {        assert( parent->baz == 13 );        v = new_v;    }};


3) The entire point of the get/set pattern is to avoid these two problems.
4) If potentially having these problems in the future is okay with you, you might as well simply use assignment syntax:

foo.bar = 3;

5) This will have the exact same drawbacks as listed above:

a) Break syntax (when extra checking needed):
foo.bar = 3; becomes foo.set_bar( 3 );

b) Add a pointer to "this":
class Bar {    Foo * parent;    int v;public:    Bar( Foo * parent ) : parent( parent ) {}    Bar & operator=( int new_v ) {        assert( parent->baz == 13 );        v = new_v;        return *this;    }};


Please note the extreme similarity between this and the previous example. You're doing the exact same amount of work.

6) Given that assignment syntax is:
*) slightly clearer (at least when dealing with nonsense values such as foo and bar)
*) easier to implement with no checking (just make the variable public)
*) the same amount of work if you want to break things after the fact

I cannot recommend your example.

This isn't even delving into how assine I consider "get/set everything" to be.
The reason I would use set/get accessors or functions is for thread safety locks. Call it over-engineering (or something less pleasant) if you like, I'd rather not trust the machine (or, in C#'s case, the runtime over Windows over the machine) to keep such operations atomic. It's iritating (on an OCD-ish level perhaps) to have 2 names for the same actual variable though. I'd really rather not have to this, so if anyone's come up with a more transparent way to do
System.Int32 GetIntegerValue (void){  lock (this.Locked)  {    return this.IntegerValue;  }}

or
System.Int32 IntegerValue{  get  {    lock (this.Locked)    {      return this.m_damnihatehungarianstylenotation_IntegerValue;    }  }}

then by all means post it.
Quote:Original post by RKillian
The reason I would use set/get accessors or functions is for thread safety locks. Call it over-engineering if you like, I'd rather not trust the machine (or, in C#'s case, the runtime over Windows over the machine) to keep such operations atomic. It's iritating (on an OCD-ish level perhaps) to have 2 names for the same actual variable though. I'd really rather not have to, so if anyone's come up with a more transparent way to do
...

then by all means post it.


obviously you need to use special measures to keep thread safety. but i would challenge that a lot of people use accessors and mutators to variables that really aren't required to be publically manipulated.

my thinking:

prefer inaccessable to accessors.

prefer just accessors to mutators.

prefer mutators to public.

public should only be used for POD in my mind...

This topic is closed to new replies.

Advertisement