Sign in to follow this  

Getting rid of Get/Set functions

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

A friend of mine asked me today if I knew a little trick to help him save the hassle of writing 10 get and 10 set methods. So I came up with a little nifty macro magic that might save you from writing those functions too. If you have basic Getter/Setters that don't go any check, using these macro's might save you 30 minutes of writing boring code.
// Getter/Setter macro's
#define SETTER(ObjectType, Varname) void Set##Varname(const ObjectType& value){ m_##Varname = value; }
#define GETTER(ObjectType, Varname) const ObjectType& Get##Varname(){ return m_##Varname; }
#define GETTERSETTER(ObjectType, Varname) void Set##Varname(const ObjectType& value){ m_##Varname = value; }const ObjectType& Get##Varname(){ return m_##Varname; }

// Get/Set function calls
#define GET(Varname) Get##Varname()
#define SET(Varname, value) Set##Varname(value)





Basic usage is like this:
class Foo
{
public:
    GETTERSETTER(float, fScaling);
    GETTERSETTER(float, fRotation);
    GETTER(std::string, TypeOf);
    SETTER(float, WeaponDamage);

private:
    float       m_fScaling;
    float       m_fRotation;
    std::string m_TypeOf;
    int         m_WeaponDamage;
};

Foo MyObject;
MyObject.SET(fScaling, 1.0f);
MyObject.SET(WeaponDamage, 10);
std::string Type = MyObject.GET(TypeOf);
Just wanted to share. The macro's aren't THE best solution, but are a quick work around if you need alot of accessor functions that don't do any checking. Feel free to use this code in whatever way, except to take over the world. Toolmaker

Share this post


Link to post
Share on other sites
#define SETTER(ObjectType, Varname) void Set##Varname(ObjectType value){ m_##Varname = value; }
^ Bad

#define SETTER(ObjectType, Varname) void Set##Varname(const ObjectType& value){ m_##Varname = value; }
^ Better

#define GETTER(ObjectType, Varname) ObjectType Get##Varname(){ return m_##Varname; }
^ Bad

#define GETTER(ObjectType, Varname) const ObjectType& Get##Varname() const { return m_##Varname; }
^ Better

EDIT: Damn, you edited your post :P

Share this post


Link to post
Share on other sites
Sorry, but that didn't seem to really help much. If you expanded the macros to declare the variable itself as well, that would look a little better. Then you would be able to do something like this:


class SomeClass
{
DECLARE_R(float, m_fReadOnly);
DECLARE_RW(float, m_fReadWrite);
DECLARE_W(float, m_fWriteOnly);

public:
SomeClass() { ... }
...
};


EDIT: I agree with Oluseyi, but if you need it, this way would still look cleaner. I really don't mind a quick copy/paste/edit to make my getters/setters, and I often do custom things in them that couldn't be handled by generic macros like that. By that, I mean validation or extra calculations to update something else.

Share this post


Link to post
Share on other sites
Quote:
Original post by Toolmaker
A friend of mine asked me today if I knew a little trick to help him save the hassle of writing 10 get and 10 set methods. So I came up with a little nifty macro magic that might save you from writing those functions too.

If you have basic Getter/Setters that don't go any check, using these macro's might save you 30 minutes of writing boring code.


i'd be concerned for your friend, first there seems to be no state invariant to maintain because the setters "don't do any checks" so having a bunch a of getters & setters is compleletly redundant it also seems from the high number of fined grained member functions i.e. the getter & setters that its representation does not vary so its seems that he has nothing more than a plain data structure there-for the members should just be public.

if it's mean't to represent a proper user-defined type then i would say he has the wrong or mixed the levels of abstraction and he probably should group some of those members into there own separate classes.

Share this post


Link to post
Share on other sites
Quote:
Original post by Toolmaker
A friend of mine asked me today if I knew a little trick to help him save the hassle of writing 10 get and 10 set methods...
Are all 10 getters and setters necessary? Maybe they are, but in my experience using getters and setters is a "quick and dirty" solution. You may be better off just using a struct with public wrapper classes. So what exactly does the class in question do? Maybe we can find a better way.

Share this post


Link to post
Share on other sites
If you've got both get and set functions then the variables might as well be public since it can be accessed by everything else anyway. If you still want the variables to be hidden in general but accessable by certain other classes/functions then declare these as friends. Instead of having both a set and get you could always just use this one instead:


class Cow
{
private:
int numLegs;

public:
int& AccessNumLegs() { return numLegs; }
};

int nLegsA = Cow.AccessNumLegs();
nLegsA++;

int& nLegsB = Cow.AccessNumLegs();
nLegsB++;






This way Cow::AccessNumLegs can be used to get legs or set legs. nLegsA is a copy and so can be changed without altering Cow just like using Get, whereas changing nLegsB will alter Cow::numLegs since its a reference and so acts like Set. Get and Set in one :) Not monkey proof though.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Wait a sec. I thought one of the primary purposes of getters/setters is to hide the implementation of the data so that now or at some future time you can change the implementation without changing the consumers of your class.

Just because there's no point at this time doesn't mean you should discard the getter/setter. It might be necessary in the future - thus the general rule to wrap it.

I'm coming from a primarily application programming background where we actually reuse our objects and code - a lot - whereas with game programming you tend to use and define it once, but I think the rule is a good one for general use.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Wait a sec. I thought one of the primary purposes of getters/setters is to hide the implementation of the data so that now or at some future time you can change the implementation without changing the consumers of your class.

This is generally the purpose of getters and setters. However, do you really need to expose these properties to the public? That is where the design issues come in. Often it is better to change your public interface so that they don't need these getters and setters.

In building getters and setters you are inheritly binding yourself to a particular implementation. While you may be able to change the underlying behavior of the getter/setter, overall you have exposed an internal detail to the public (the datatype specifically) which they may not even need to know.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Wait a sec. I thought one of the primary purposes of getters/setters is to hide the implementation of the data so that now or at some future time you can change the implementation without changing the consumers of your class.

Just because there's no point at this time doesn't mean you should discard the getter/setter. It might be necessary in the future - thus the general rule to wrap it.

I'm coming from a primarily application programming background where we actually reuse our objects and code - a lot - whereas with game programming you tend to use and define it once, but I think the rule is a good one for general use.


In all areas of programming, get/set tuples are a code smell. They don't do any useful work because they don't abstract anything. If they actually do something, then they are very poorly named mutators.

It doesn't make sense to add abstraction you don't need to software. You can always do more work and add more abstraction, it's a run-away train scenario.

If you do need to change the behavior of the get/set later, you've violated interface contract and it's version should be bumped - this is a significant change to the design. Not compiling might be a good thing, it makes you review the code and ensure it will still work correctly with the new behavior.

All modern C++ compilers have a property extention to make get/set function transparent and a simple template adaptor can turn a member pointer into a functor (e.g. mem_accessor(&Circle::x) ).

Share this post


Link to post
Share on other sites
USE A CLASS TO ENFORCE INVARIANTS

IF IT'S A STRUCTURE WHOSE MEMBERS CAN HAVE ANY VALUE, MAKE IT A POD, FORCHRISSAKES

PS: You should really rename this thread to "Hiding/Obfuscating Getter/Setter functions"

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
Wait a sec. I thought one of the primary purposes of getters/setters is to hide the implementation of the data so that now or at some future time you can change the implementation without changing the consumers of your class.

Just because there's no point at this time doesn't mean you should discard the getter/setter. It might be necessary in the future - thus the general rule to wrap it.

I'm coming from a primarily application programming background where we actually reuse our objects and code - a lot - whereas with game programming you tend to use and define it once, but I think the rule is a good one for general use.


There is a simillar thread to this going on so i'll just qoute my-self with an appropriate answer.

Quote:
Original post by snk_kid
The reason why we encapsulate data meaning making data members private to enforce access and update through member functions i.e. getters & setters are:

1. You determine that your type's represenstation is variable, meaning its data members can change over-time be it the name or the type of the memeber, if you did not encapsulate the variant then clients of your type will be tightly coupled to its representation thus if your type's represenstation changes then all clients are forced to update there code to reflect the changes and then recompile it all.

By encapsulating the variant you make loose coupling by indirection, enforcing clients to access/update through an invariant interface i.e. member functions.

2. You determine that your type has a state invariant meaning that the representation has range of valid values but clients are allowed to update the representation so to enforce the state invariant you make the representation private and enforce clients to use the interface i.e. member functions to update without putting the instance of that type in an undefined state. If the represenstation is public how could you ever maintain the state invariant from clients? exactly you couldn't clients could easliy set invalid values into public data members.

So to summarize this:



  • encapsulate the variation/variant and provide invariant interface to it <-- important is the first key to abstraction


  • if your type has a state invariant then encapsulate it by making it private and enforce access/update through the interface i.e. member functions, there-for never putting an instance of that type in an undefined state.



If your type has none of these criteria then there is no reason to make it private, your type probably is not a real type and is nothing more than an aggregate/compound data structure.

A very good example of a type that does not encapsulate its data members and nor does it need to is the standard library type std::pair, a pair has 2 members and this will never change it has no state invariant to maintain there-for its members are public.

Also note if your type has lots of small fine grained accessor methods i.e getters/setters then again you've modelled your type at the wrong or mixed the levels of abstraction and you've probably got nothing more than a an aggregate/compound data structure. If its mean't to really represent a proper type then perhaps your type's representation should be grouped into new types.

Share this post


Link to post
Share on other sites
Quote:
Original post by Magmai Kai Holmlor
In all areas of programming, get/set tuples are a code smell. They don't do any useful work because they don't abstract anything. If they actually do something, then they are very poorly named mutators.


So the question begs to be asked: why were they introduced in the first place? Is this a case of the class designers deciding that "hey, this is a great idea, and it builds on the data hiding aspect!" (Why make a variable private? So no one can mess with it. Why make a variable protected? So your child classes can access and change it. Why make a variable public? Uh... I don't know, why?)

Second: what, exactly, would be the difference between a mutator and a "setter"? In my mind they are identical. Is there a distinction I'm missing? The purpose of a mutator is to change the variable value. The purpose of the setter is to change the variable value.

I end up using - well, properties in C# - to fire off events for variables as they're changed and to validate the information coming in. I've always assigned equal providence to properties in C# and the getter/setter pattern in C++. The only benefit properties have had is that they are invisible to the class user. Getters/Setters are not, not the way I've created and used them. (Which is greatly improved by the code samples in this thread.) Are properties more worthwhile because they're invisible? I've always recognized that you can later abstract a property into a variable's place since you can use the two interchangeably, so later data validation, event triggering, etc., can happen if needed without changing the contract proferred by the class.

Quote:
Original post by Magmai Kai Holmlor
All modern C++ compilers have a property extention to make get/set function transparent and a simple template adaptor can turn a member pointer into a functor (e.g. mem_accessor(&Circle::x) ).


This I did not know. In all the time I've read and played with C++ I've never come across this factoid or, more importantly, the usage of it. That boggles my mind as properties are *nice*. :)

Thanks, as always, for the enlightening conversation.

Share this post


Link to post
Share on other sites
Get/Setters are only a logical abstraction to ANY form of mutators and such..

it means that, instead of exposing direct access to the variables, you should have methods that change the state, and methods, that return the state.

so you have Getters, that get information (but not GetThisVar, GetThatVar.. methods like TimeInSeconds, TimeInMinutes, etc.. or IsAlive, Count, Size, etc..)

and Setters, that set/change the object state.. (but not SetThisVar, SetThatVar.. methods like Increment, IterateToNext, ReflectTo, Invert, etc..)

but somehow, that naming to call them getters, and setters (because they get state, and set state) was shown in simple examples with real GetVar, SetVar, and the result is that bad wrong knowledge that we have today.. an abfucktion of the original purpose, wich is still a good one.

Share this post


Link to post
Share on other sites
I'm getting confused about this [smile] Everyone's talking about "redesigning" the class not to use getter and setters...

Well - what about an example? Say, you want to design a Triangle class. It contains three variables that hold the position of each of the vertices (some kind of POINT structures). Then, the triangle has a color assigned to it. Also it has some nice functions to draw itself, or calucalate some things about itself. So - how could this be designed?

Oxyd

Share this post


Link to post
Share on other sites
Quote:
Original post by Oxyd
I'm getting confused about this [smile] Everyone's talking about "redesigning" the class not to use getter and setters...

Well - what about an example? Say, you want to design a Triangle class. It contains three variables that hold the position of each of the vertices (some kind of POINT structures). Then, the triangle has a color assigned to it. Also it has some nice functions to draw itself, or calucalate some things about itself. So - how could this be designed?

Oxyd


A Triangle is a very basic thing which doesn't need to do much work. These design principles are more for objects which actually do something... however we could stretch this a little by imagining a Triangle class which does have to do some work.

For example say you had a Triangle which was constructed by taking the length of two sides, AB and BC, the angle between them, the x and y position of their shared vertex B, and the angle of the the first side (AB) relative to some axis. This is 6 pieces of information to define a triangle.

Internally you decide to store the three vertices, you also calculate the length of the third side and store it with the others because they're useful to you.

What if you then wanted to change one of these pieces of information that you used to create the triangle? E.g. what if you want to change the length of one of the sides?

If you call SetLengthAB it will also change the length of CA. It will also change the position of A.

So GetLengthCA will return a different value before and after a call to SetLengthAB. Not particularly intuitive but correct all the same.

What you're really doing is redefining the whole triangle not just an individual length or an individual vertex. It would be clearer (if laughable), to have a function RedefineWholeTriangleUsingSideAB(length);

In a larger design it better expresses what is going on and wouldn't surprise you that repeated calls to a seemingly unrelated function, GetLengthCA, returned different values.

Share this post


Link to post
Share on other sites
Quote:
Original post by Magmai Kai Holmlor
In all areas of programming, get/set tuples are a code smell.

Well, what about a trivial example like this:

void SetWindowSize(int w, int h);
pair<int, int> GetWindowSize();

How would you write this code?
Quote:
Original post by Magmai Kai Holmlor
They don't do any useful work because they don't abstract anything.

Suppose you designed your Window class as follows. The default constructor initializes everything (x, y, width, height, title) with reasonable default values. If you call SetWindowSize() it simply changes the private members. Once you call Create(), the window is actually created. At this point if you call SetWindowSize() again, not only will it change the properties but also call appropriate code to actually modify the existing window's size. How would you go about implementing this?
Quote:
Original post by Magmai Kai Holmlor
All modern C++ compilers have a property extention to make get/set function transparent and a simple template adaptor can turn a member pointer into a functor (e.g. mem_accessor(&Circle::x) ).

What are these extensions for MSVC and GCC? I couldn't find any info online. Your accessor takes care of a very dumb pair of getters/setters (still nice, but essentially just syntatic sugar). How would you implement properties that actually do something besides changing the member (say going to the database)? I suppose one could write a generic property class that takes advantage of boost's lambda library but I'm not sure how useful that would be in practice. I certainly haven't seen such implementations, it'd be cool if someone could point one out or provide a simple example.

EDIT: Also, how can you use your accessor for the above example? The function accepts two parameters (to save the user from doing make_pair) but returns a pair to avoid the ugliness of using references in order to return two values. If you extend this to an arbitrary tuple (boost's implementation, for instance), how would you implement an accessor for an arbitrary number of parameters (with specialization that returns a simple value instead of a tuple for one parameter)? Using typelists? I'm new to templates so I'm having some trouble visualizing the implementation.

EDIT: It's suprising that boost doesn't include a property implementation. Perhaps we can design one together and submit it for peer review?

This discussion is awesome [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by Oxyd
I'm getting confused about this [smile] Everyone's talking about "redesigning" the class not to use getter and setters...


No we are not saying that, well i'm not if you read the thread carefully this is what sparked it off:

Quote:
Original post by Toolmaker
...
if you need alot of accessor functions that don't do any checking...


There is no point, if your type's representation does not vary and your type's representation does not have a state invariant to maintain then there isn't any point in making its representation private. Read my last post for more on that.

Also if there really is a need to encapsulate say to maintain the state invariant but you have lots of fine grained getters & setters then you've probably modelled your type at the wrong level or mixed levels of abstraction, its to low-level it should either be redesigned or its should be used in conjunction with another type that is at a higher level for clients to use.

If i saw some ones class with lots of getters & setters i would say that person never designed that class at all they just coded it along the way.

Quote:
Original post by Talonius
So the question begs to be asked: why were they introduced in the first place?


simple they where not, getters & setters are not a concept.

Quote:
Original post by Talonius
Is this a case of the class designers deciding that "hey, this is a great idea, and it builds on the data hiding aspect!"


To hide data is not the same as the reason why to hide it in the first place and its usually to encapsulate variants with an invariant interface to clients that usually maintains state invariants aswell.

Quote:
Original post by Talonius
(Why make a variable private? So no one can mess with it.


Not when you have a setter that does no checking, everyone can still mess with it.

Quote:
Original post by Talonius
Why make a variable protected? So your child classes can access and change it.


Making a data members protected is the biggest contridication ever, this is usually a sign of bad design, "why?" you ask

well your hiding it from un-related types so "no one can mess with it" or in my terms to maintain a state invariant and/or to encapsulate variant representation but making it protected you let everyone mess with it by deriving from it.

Quote:
Original post by Talonius
Why make a variable public? Uh... I don't know, why?)


because your asserting to clients that the type's representation does not or will not change, and there is no state invariant to maintain, and your asserting its logically part of the type's interface because that is how your design turn out to be.

At the end of the day it all depends on the requirements spec of your problem domain.

Share this post


Link to post
Share on other sites
Quote:
Original post by CoffeeMug
What are these extensions for MSVC

__declspec(property(get=GetX, put=SetX)) int X;

If you just want an accessor, leave off the put part.

Quote:
It's suprising that boost doesn't include a property implementation. Perhaps we can design one together and submit it for peer review?

The problem with properties is that you essentially have to store two member function pointers for a little syntactic sugar. I may be Texan at heart but I don't like my objects *that* big. :) Can you imagine how large a WinForm-ish class would be like that?

The property extension on MSVC merely rewrites property gets/sets in-terms of the member functions, even when you say o.X += 1 (expands out into o.SetX(o.GetX() + 1)).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by Toolmaker
A friend of mine asked me today if I knew a little trick to help him save the hassle of writing 10 get and 10 set methods. So I came up with a little nifty macro magic that might save you from writing those functions too.

If you have basic Getter/Setters that don't go any check, using these macro's might save you 30 minutes of writing boring code.

*** Source Snippet Removed ***

Basic usage is like this:

class Foo
{
public:
GETTERSETTER(float, fScaling);
GETTERSETTER(float, fRotation);
GETTER(std::string, TypeOf);
SETTER(float, WeaponDamage);

private:
float m_fScaling;
float m_fRotation;
std::string m_TypeOf;
int m_WeaponDamage;
};

Foo MyObject;
MyObject.SET(fScaling, 1.0f);
MyObject.SET(WeaponDamage, 10);
std::string Type = MyObject.GET(TypeOf);


Just wanted to share. The macro's aren't THE best solution, but are a quick work around if you need alot of accessor functions that don't do any checking.

Feel free to use this code in whatever way, except to take over the world.

Toolmaker


If any person I was working with were to show me code like this, I would feel a severe urge to strangle them.

Your code is clever. Clever code is bad code, as any experienced software person will tell you. It is useless beyond the "hey, look what I can do" examples like the one you have above.

Share this post


Link to post
Share on other sites
Quote:
Original post by antareus
__declspec(property(get=GetX, put=SetX)) int X;

Thanks. I'd never use this monstrosity though [smile]
Quote:
Original post by antareus
The problem with properties is that you essentially have to store two member function pointers for a little syntactic sugar.

I think writing member functions and then wrapping them into a property with two function pointers is idiotic. Just use the damned member functions! A better idea would be some sort of a template solution (perhaps using boost::lambda?) that lets you write accessor code in place and generates a structure for each property that has no memory overhead. Perhaps something that would be used like this:

class MyClass
{
public:
property<int>
(
// accessor
return m_Value;
,
// mutator
m_Value = _1;
) Length;
};

And then

MyClass c;
c.Length = 15;
cout << c.Length;

Share this post


Link to post
Share on other sites
To be annoying: What if we wanted the Triangle class to be simple. Say, you just need it to draw a triangle on the screen (writing your own renderer, or whatever). So it's basically a structure with draw () method... Would it be good idea, to make the vertices public? What if I later wanted to add some fancy feature, like checking wheter the triangle isn't out of screen with the new value?

Oxyd

Share this post


Link to post
Share on other sites

This topic is 4836 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this