Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

A replacement for getters/setters ?

63 views
Skip to first unread message

JiiPee

unread,
Feb 11, 2016, 11:20:11 AM2/11/16
to
I have always used getters/setters but now I read about them being
"evil": http://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html

Lets have an example:

class PersonDetails
{
private:
string name;
int age;
};

Now, how would you get access to name and age without getters and
setters? Lets say we have new information about the persons name.... its
now "John Smith", was "John".
So how to change that name without a setter?


K. Frank

unread,
Feb 11, 2016, 12:15:48 PM2/11/16
to
Hi JiiPee!
I, very frequently, just access the data members directly.
Of course, they have to be public to do this:

class PersonDetails
{
public:
string name;
int age;
};

or

struct PersonDetails
{
string name;
int age;
};

Then just access them:

PersonDetails pd;
pd.name = "John Smith";

The simpler the class, the less it has class invariants,
and the more POD-ish (plain old data) it is, the more likely
I am to make data members public, and access them directly.

(Stylistically, I often use "struct" instead of "class" for
classes that are "morally" POD, as well as for true POD classes.)

Having said that, I don't think that getters/setters are
evil -- they're just something of a nuisance, especially
in simple settings.


Best.


K. Frank

Paavo Helde

unread,
Feb 11, 2016, 1:05:59 PM2/11/16
to
If you read a bit past the headline of your link, then you see that he
does not advocate removing the setters, but renaming them:

person.TakeNewName("John Smith");

person.LiveAndSuffer(Years(30));

Not sure if this is useful for anything.


Scott Lurndal

unread,
Feb 11, 2016, 1:20:25 PM2/11/16
to
Create a new instance of the object and destroy the original. e.g. have
a constructor that takes a reference to the orignal and the updated
name.

PersonalDetails(PersonalDetails& orig, string newname)
{
name = newname;
age = orig.age;
}

Wouter van Ooijen

unread,
Feb 11, 2016, 2:09:33 PM2/11/16
to
Op 11-Feb-16 om 5:19 PM schreef JiiPee:
First, think if it realy makes sense to change the name of the person.
Did he/she realy apply for a name change and got permission? And instead
of age, why not store the date of birth (which is not likely to change)?

Next, pure getters and setters make sense when there is a significant
chance that at some moment in the life cycle of your software, you will
change the private data without a change in the interface. If you need
to do this, you will be very gratefull for the abstraction of the
getter/setters.

If the chance that you will do that is (almost) zero, getters/setters
are a nuisance, and you should instead make the attributes public.

Non-pure getters/setters (that do something more than just
setting/getting the attribute) are of course a different story.

Wouter van Ooijen

Alf P. Steinbach

unread,
Feb 11, 2016, 2:42:02 PM2/11/16
to
On 2/11/2016 8:09 PM, Wouter van Ooijen wrote:
>
> [snip]
> pure getters and setters make sense when there is a significant
> chance that at some moment in the life cycle of your software, you will
> change the private data without a change in the interface. If you need
> to do this, you will be very gratefull for the abstraction of the
> getter/setters.
>
> If the chance that you will do that is (almost) zero, getters/setters
> are a nuisance, and you should instead make the attributes public.

Requirements can change.

And they do.

Bertrand Meyer thought that this was important enough to make member
function invocations look like data attribute access in Eiffel, so that
a data attribute could be replaced with a member function or vice versa
without affecting client source code. He called this the [1]“uniform
access principle”. I his words, in his 1988 book [2]“Object Oriented
Software Construction” (which really was a combined introduction to and
rationale of Eiffel, sort of like a combination of Bjarne's TCPPL and
Design & Evolution books): “All services offered by a module should be
available through a uniform notation, which does not betray whether they
are implemented through storage or through computation”.

In C++ one can implement uniform access by implementing read only
properties, but this has both a memory cost (back-pointer to the object
in each such attribute) and an execution cost (extra indirection).

I think the uniform access principle is the least weak argument for C++
language support for properties. But ideally, when a direct data
attribute is replaced with a read-only property function, that function
should be a /pure function/, possibly except caching of results, to
avoid the property-with-side-effects nightmare of e.g. properties in C#.
And the only guaranteed pure functions in current C++ are `constexpr`
functions, which is too restrictive to be useful for this.


> Non-pure getters/setters (that do something more than just
> setting/getting the attribute) are of course a different story.

Yes.


Cheers,

- Alf

Notes:
[1] <url: https://en.wikipedia.org/wiki/Uniform_access_principle>
[2] <url:
https://en.wikipedia.org/wiki/Object-Oriented_Software_Construction>

Wouter van Ooijen

unread,
Feb 11, 2016, 2:51:27 PM2/11/16
to
Op 11-Feb-16 om 8:41 PM schreef Alf P. Steinbach:
> On 2/11/2016 8:09 PM, Wouter van Ooijen wrote:
>>
>> [snip]
>> pure getters and setters make sense when there is a significant
>> chance that at some moment in the life cycle of your software, you will
>> change the private data without a change in the interface. If you need
>> to do this, you will be very gratefull for the abstraction of the
>> getter/setters.
>>
>> If the chance that you will do that is (almost) zero, getters/setters
>> are a nuisance, and you should instead make the attributes public.
>
> Requirements can change.

That's why my statement doesn'te even mention the (current)
requirements. I ask for a judgement call about the future.
Getters/setters are a nuisance, but a very small one compared to the
updating of a large amount of client code.

But there are some cases in which IMO public attributes are the bettre
choice, for instance locations (x,y coordinate pairs) on a small
(embedded) LCD screen. No chnace in hell that I will ever replace them
with an angle/distance pair. But as said, when in doubt favour
getters/setters.

Wouter van Ooijen

JiiPee

unread,
Feb 11, 2016, 2:56:45 PM2/11/16
to
ok, this has a point.... have to think about....
So instead of setter, we would always pass the object and the new value.

JiiPee

unread,
Feb 11, 2016, 2:58:42 PM2/11/16
to
On 11/02/2016 19:09, Wouter van Ooijen wrote:
> Op 11-Feb-16 om 5:19 PM schreef JiiPee:
>> I have always used getters/setters but now I read about them being
>> "evil":
>> http://www.yegor256.com/2014/09/16/getters-and-setters-are-evil.html
>>
>> Lets have an example:
>>
>> class PersonDetails
>> {
>> private:
>> string name;
>> int age;
>> };
>>
>> Now, how would you get access to name and age without getters and
>> setters? Lets say we have new information about the persons name.... its
>> now "John Smith", was "John".
>> So how to change that name without a setter?
>
>
> If the chance that you will do that is (almost) zero, getters/setters
> are a nuisance, and you should instead make the attributes public.

Sutter argues strongly that you should always use functions to get
access to data members....

JiiPee

unread,
Feb 11, 2016, 3:03:03 PM2/11/16
to
On 11/02/2016 19:51, Wouter van Ooijen wrote:
> But there are some cases in which IMO public attributes are the bettre
> choice, for instance locations (x,y coordinate pairs)

here I have agreed.... My point class has just int x,y; ... i find
it difficult to have: int getX(); I dont like:
center.X();

but rather:

center.x

Mr Flibble

unread,
Feb 11, 2016, 3:32:48 PM2/11/16
to
Strictly speaking only those (non-const) member variables that
contribute to a class's invariant need be kept private. Obviously if
changing the name of a person should be reflected by updating some GUI
widget then you would want to use a setter function.

/Flibble


Scott Lurndal

unread,
Feb 11, 2016, 3:48:55 PM2/11/16
to
Well, I personally have no problem with getters and setters. I don't
see a need for a specific naming convention, however.

Vir Campestris

unread,
Feb 11, 2016, 4:18:19 PM2/11/16
to
On 11/02/2016 19:41, Alf P. Steinbach wrote:
> Bertrand Meyer thought that this was important enough to make member
> function invocations look like data attribute access in Eiffel, so that
> a data attribute could be replaced with a member function or vice versa
> without affecting client source code

That's one of the things C# and Java have got right.

The good thing about setters instead of exposing data is that you can do
more with them. So I can have

void NewAge(int age)
{
#ifdef DEBUG
trace << "Age updated to " << age;
if (age > 127) throw ICBA;
#endif
m_age = age;
}

to trace and catch errors - without changing the calling code.

Andy

Wouter van Ooijen

unread,
Feb 11, 2016, 5:42:06 PM2/11/16
to
Op 11-Feb-16 om 9:32 PM schreef Mr Flibble:
There are other things besides contributing to the invariant that can be
usefull, for instance logging and caching.

>
> /Flibble

Who? Fibble? The nonsense guy makes a remark that makes some sense? Did
they put something in your saugages?

Wouter

Daniel

unread,
Feb 11, 2016, 9:06:29 PM2/11/16
to
On Thursday, February 11, 2016 at 5:42:06 PM UTC-5, Wouter van Ooijen wrote:
> > /Flibble
>
> Who? Fibble? The nonsense guy makes a remark that makes some sense?

It's Flibble, if you please.

Daniel

Cholo Lennon

unread,
Feb 12, 2016, 7:36:42 AM2/12/16
to
I agree with you.

Also IMO a getter/setter can have a non trivial implementation (i.e.
provide a synchronous access to data). Another advantage over public
data members is that calls to them can be deferred in time with
std::function/std::bind.

Regards

--
Cholo Lennon
Bs.As.
ARG


Scott Lurndal

unread,
Feb 12, 2016, 8:40:16 AM2/12/16
to
They also provide for the abstraction of the underlying data type,
which then can be changed without changing the clients of the public
class interface.

Bo Persson

unread,
Feb 12, 2016, 11:13:00 AM2/12/16
to
They become evil when people write code like

pd.setAge(pd.getAge() + 1);

and believe they have done something proper.


Bo Persson


Hans Bos

unread,
Feb 12, 2016, 5:53:32 PM2/12/16
to

"Cholo Lennon" <cholo...@hotmail.com> wrote in message
news:n9kjjo$62s$1...@gioia.aioe.org...


...
> Also IMO a getter/setter can have a non trivial implementation (i.e.
> provide a synchronous access to data). Another advantage over public data
> members is that calls to them can be deferred in time with
> std::function/std::bind.
>

You can use std::function and std::bind with data members as well since they
are defined in terms of INVOKE (or std::invoke).
You can call std::invoke with a pointer to member and an object pointer.

Greetings,
Hans.

0 new messages