Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #67849 > unrolled thread

About getters/setters

Started byJiiPee <no@notvalid.com>
First post2019-08-21 20:22 +0100
Last post2019-08-23 15:49 +0000
Articles 20 — 9 participants

Back to article view | Back to comp.lang.c++


Contents

  About getters/setters JiiPee <no@notvalid.com> - 2019-08-21 20:22 +0100
    Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-21 19:34 +0000
    Re: About getters/setters Bo Persson <bo@bo-persson.se> - 2019-08-21 21:40 +0200
    Re: About getters/setters Öö Tiib <ootiib@hot.ee> - 2019-08-21 12:52 -0700
      Re: About getters/setters JiiPee <no@notvalid.com> - 2019-08-22 15:25 +0100
        Re: About getters/setters Öö Tiib <ootiib@hot.ee> - 2019-08-22 09:06 -0700
          Re: About getters/setters Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-08-24 04:32 -0700
    Re: About getters/setters Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-08-22 15:09 -0700
      Re: About getters/setters Ian Collins <ian-news@hotmail.com> - 2019-08-23 16:17 +1200
        Re: About getters/setters Tim Rentsch <tr.17687@z991.linuxsc.com> - 2019-08-23 05:26 -0700
        Re: About getters/setters Melzzzzz <Melzzzzz@zzzzz.com> - 2019-08-23 18:07 +0000
      Re: About getters/setters JiiPee <no@notvalid.com> - 2019-08-23 07:09 +0100
    Re: About getters/setters JiiPee <no@notvalid.com> - 2019-08-23 07:13 +0100
      Re: About getters/setters David Brown <david.brown@hesbynett.no> - 2019-08-23 09:30 +0200
        Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-25 06:16 +0000
          Re: About getters/setters David Brown <david.brown@hesbynett.no> - 2019-08-25 12:12 +0200
    Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-23 11:24 +0000
      Re: About getters/setters James Kuyper <jameskuyper@alumni.caltech.edu> - 2019-08-23 08:34 -0400
        Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-23 14:48 +0000
        Re: About getters/setters Jorgen Grahn <grahn+nntp@snipabacken.se> - 2019-08-23 15:49 +0000

#67849 — About getters/setters

FromJiiPee <no@notvalid.com>
Date2019-08-21 20:22 +0100
SubjectAbout getters/setters
Message-ID<kSg7F.32840$Xs5.970@fx06.am4>
Which one is better:

1)

class Person

{

public:

int getAge() { return age;}

void setAge(int a) { age = a;}

private:

int age;

};

or

2)

struct Person

{

int age;

};

####

I know Herb Sutter recommended 1) but for example isocpp

https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get

seems to recommend 2). Herb says that for example when debugging 1) is 
good because you can write to file all the accesses of the age, or cout 
all the calls. Also debugger can stop at the function call, but can 
debugger stop at :

person.age = 6;

?

So debugger can put a red dot to setAge and see which object changed it. 
And cout/write on file information.

Argument also, that later on can add other functionality punder setAge 
(like cache logic).

But 2) people argue its so simple and not likely to change, so it breaks 
OO idea.

I do currently 1) but wondering which way to go.

Like now I have a "Settings" class. Simple data members. I started 
adding getters and setters....

[toc] | [next] | [standalone]


#67852

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-08-21 19:34 +0000
Message-ID<slrnqlr75s.cdo.grahn+nntp@frailea.sa.invalid>
In reply to#67849
On Wed, 2019-08-21, JiiPee wrote:
> Which one is better:
>
> 1)
>
> class Person
> {
> public:
> int getAge() { return age;}

There's a const missing.

> void setAge(int a) { age = a;}
>
> private:
> int age;
> };
>
> or
>
> 2)
>
> struct Person
> {
> int age;
> };

Or one which is not invalidated by time itself:

struct Person {
    explicit Person(const Date& birthday);
    const Date birthday;
};

(Ignoring intricacies of hours, minutes and time zones, and people of
unknown age.)

It depends on what you're modeling and how you want to model it.
Saying one is better than the other is like saying a spoon is better
than a fork.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#67854

FromBo Persson <bo@bo-persson.se>
Date2019-08-21 21:40 +0200
Message-ID<gs5l26F48alU1@mid.individual.net>
In reply to#67849
On 2019-08-21 at 21:22, JiiPee wrote:
> Which one is better:
> 
> 1)
> 
> class Person
> 
> {
> 
> public:
> 
> int getAge() { return age;}
> 
> void setAge(int a) { age = a;}
> 
> private:
> 
> int age;
> 
> };
> 
> or
> 
> 2)
> 
> struct Person
> 
> {
> 
> int age;
> 
> };
> 
> ####
> 
> I know Herb Sutter recommended 1) but for example isocpp
> 
> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
> 
> seems to recommend 2). Herb says that for example when debugging 1) is 
> good because you can write to file all the accesses of the age, or cout 
> all the calls. Also debugger can stop at the function call, but can 
> debugger stop at :
> 
> person.age = 6;
> 
> ?
> 
> So debugger can put a red dot to setAge and see which object changed it. 
> And cout/write on file information.
> 
> Argument also, that later on can add other functionality punder setAge 
> (like cache logic).
> 
> But 2) people argue its so simple and not likely to change, so it breaks 
> OO idea.
> 
> I do currently 1) but wondering which way to go.
> 
> Like now I have a "Settings" class. Simple data members. I started 
> adding getters and setters....
> 

There probably isn't a general answer, except that it depends.

If you model a real person, the age doesn't change except by +1 on each 
birthday. So what is the use for setAge?


In the Core Guidelines you have a Point(x, y) where it is unclear what 
the use for set_x is. So you could just skip it.

If the class were to have some kind of behavior, perhaps a 
Point.move_to(somewhere) would be more useful?


So, it depends.  :-)


     Bo Persson

[toc] | [prev] | [next] | [standalone]


#67856

FromÖö Tiib <ootiib@hot.ee>
Date2019-08-21 12:52 -0700
Message-ID<c053c20c-9b56-49c4-ab0a-0d060faa3c89@googlegroups.com>
In reply to#67849
On Wednesday, 21 August 2019 22:23:08 UTC+3, JiiPee  wrote:
> Which one is better:
> 
> 1)
> 
> class Person
> 
> {
> 
> public:
> 
> int getAge() { return age;}
> 
> void setAge(int a) { age = a;}
> 
> private:
> 
> int age;
> 
> };
> 
> or
> 
> 2)
> 
> struct Person
> 
> {
> 
> int age;
> 
> };

Age is rapidly changing property of a person so it is usually made as
getter function that calculates it based on date of birth of person
and current date. Date of birth is usually const set in constructor
since that can't change during life-time (or even after) of a person.

Snipping possible misrepresentation of Herb Sutter and
CppCoreGuidelines of isocpp.

> I do currently 1) but wondering which way to go.

I think you should do in usual way (that I desribed).

[toc] | [prev] | [next] | [standalone]


#67877

FromJiiPee <no@notvalid.com>
Date2019-08-22 15:25 +0100
Message-ID<dBx7F.346070$c8w1.123079@fx08.am4>
In reply to#67856
On 21/08/2019 20:52, Öö Tiib wrote:
> Snipping possible misrepresentation of Herb Sutter and
> CppCoreGuidelines of isocpp.


Sutter says like: "Always make all data members private. The only 
exception is c-style struct where all members are public"

So he was against putting some private and some public. And he proves 
his point.

So according to him if Person class has some functions (like increasing 
the age automatically) then the age itself should be private and if its 
value is needed we need a getter.

[toc] | [prev] | [next] | [standalone]


#67879

FromÖö Tiib <ootiib@hot.ee>
Date2019-08-22 09:06 -0700
Message-ID<1a05f743-f9a4-47e5-8dc6-64abab4195b0@googlegroups.com>
In reply to#67877
On Thursday, 22 August 2019 17:25:24 UTC+3, JiiPee  wrote:
> On 21/08/2019 20:52, Öö Tiib wrote:
> > Snipping possible misrepresentation of Herb Sutter and
> > CppCoreGuidelines of isocpp.
> 
> 
> Sutter says like: "Always make all data members private. The only 
> exception is c-style struct where all members are public"

CppCoreGuidelines at
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get>
does not conflict with it just suggest to prefer that c-style struct
to all trivial setters and getters. That is why your claim seemed
misrepresentation.

> So he was against putting some private and some public. And he proves 
> his point.

Your OP did not discuss putting some data members private and
some public, both are against it:
<https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#c134-ensure-all-non-const-data-members-have-the-same-access-level>

> So according to him if Person class has some functions (like increasing 
> the age automatically) then the age itself should be private and if its 
> value is needed we need a getter.

What you seemingly asked in your OP was if to have trivial setters
and getters or to have c-style struct. "Getter" is red herring
since you don't need one with c-style struct.

[toc] | [prev] | [next] | [standalone]


#67924

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-08-24 04:32 -0700
Message-ID<86h86623z3.fsf@mailhub.linuxsc.com>
In reply to#67879
Tiib <ootiib@hot.ee> writes:

> On Thursday, 22 August 2019 17:25:24 UTC+3, JiiPee  wrote:
>
>> On 21/08/2019 20:52, Tiib wrote:
>>
>>> Snipping possible misrepresentation of Herb Sutter and

Strange comment considering that nowhere in the thread is any
reference given for Herb Sutter's views.  Given that you don't
know what Herb Sutter writings JiiPee means to refer to here,
there is no basis for claiming a misrepresentation, or even
a possible misrepresentation (except in the vacuous sense that
"all things are possible").

>>> CppCoreGuidelines of isocpp.
>
>> Sutter says like:  "Always make all data members private.  The only
>> exception is c-style struct where all members are public"
>
> CppCoreGuidelines at
> <https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get>
> does not conflict with it just suggest to prefer that c-style struct
> to all trivial setters and getters.  That is why your claim seemed
> misrepresentation.

For what it's worth, I think JiiPee's comments offer a more
faithful representation of the core guidelines document than
yours do.

[toc] | [prev] | [next] | [standalone]


#67890

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-08-22 15:09 -0700
Message-ID<86y2zk26ps.fsf@mailhub.linuxsc.com>
In reply to#67849
JiiPee <no@notvalid.com> writes:

[some white space reformatting done]

> Which one is better:  1)
>
>     class Person {
>       public:
>         int getAge() { return age;}
>         void setAge(int a) { age = a;}
>       private:
>         int age;
>     };
>
> or  2)
>
>     struct Person {
>         int age;
>     };
>
> ####
>
> I know Herb Sutter recommended 1) but for example isocpp
>
> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>
> seems to recommend 2). [...]
>
> I do currently 1) but wondering which way to go.
>
> Like now I have a "Settings" class.  Simple data members.  I started
> adding getters and setters....

I agree with Herb Sutter's recommendation that (assuming the
class or struct has some member functions) data members should
never be public.  There are cases where for data members might
plausibly be made protected rather than private, but never
public.  (Incidentally I am ignoring the "age/birthday" matter
that some other people have commented on, and assuming your
question is meant as generic, with 'age' being merely an
unfortunate choice of example.)

I suggest however a slightly different pattern than (1), along
these lines (disclaimer: not compiled):

    class Person {
        unsigned siblings_;
        // ... other data members ...

      public:
        // ... other member functions

              unsigned &siblings()       { return siblings_; }
        const unsigned &siblings() const { return siblings_; }
    };

Now our accessor functions look more like data member access, but
they remain functions:

    if(  fred.siblings() > 0  )  ...

    fred.siblings() += 1;  // a new birth in fred's family

To me this pattern reads nicer on the client side than set/get
functions.

[toc] | [prev] | [next] | [standalone]


#67897

FromIan Collins <ian-news@hotmail.com>
Date2019-08-23 16:17 +1200
Message-ID<gs97lsF3s0U2@mid.individual.net>
In reply to#67890
On 23/08/2019 10:09, Tim Rentsch wrote:
> JiiPee <no@notvalid.com> writes:
> 
> [some white space reformatting done]
> 
>> Which one is better:  1)
>>
>>      class Person {
>>        public:
>>          int getAge() { return age;}
>>          void setAge(int a) { age = a;}
>>        private:
>>          int age;
>>      };
>>
>> or  2)
>>
>>      struct Person {
>>          int age;
>>      };
>>
>> ####
>>
>> I know Herb Sutter recommended 1) but for example isocpp
>>
>> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>>
>> seems to recommend 2). [...]
>>
>> I do currently 1) but wondering which way to go.
>>
>> Like now I have a "Settings" class.  Simple data members.  I started
>> adding getters and setters....
> 
> I agree with Herb Sutter's recommendation that (assuming the
> class or struct has some member functions) data members should
> never be public.  There are cases where for data members might
> plausibly be made protected rather than private, but never
> public.

There is a case where a data member is safe to be public:  a const data 
member.  Access to such a member cannot change a class's invariants.

-- 
Ian.

[toc] | [prev] | [next] | [standalone]


#67904

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2019-08-23 05:26 -0700
Message-ID<86tva8131e.fsf@mailhub.linuxsc.com>
In reply to#67897
Ian Collins <ian-news@hotmail.com> writes:

> On 23/08/2019 10:09, Tim Rentsch wrote:
>
>> JiiPee <no@notvalid.com> writes:
>>
>> [some white space reformatting done]
>>
>>> Which one is better:  1)
>>>
>>>      class Person {
>>>        public:
>>>          int getAge() { return age;}
>>>          void setAge(int a) { age = a;}
>>>        private:
>>>          int age;
>>>      };
>>>
>>> or  2)
>>>
>>>      struct Person {
>>>          int age;
>>>      };
>>>
>>> ####
>>>
>>> I know Herb Sutter recommended 1) but for example isocpp
>>>
>>> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>>>
>>> seems to recommend 2).  [...]
>>>
>>> I do currently 1) but wondering which way to go.
>>>
>>> Like now I have a "Settings" class.  Simple data members.  I started
>>> adding getters and setters....
>>
>> I agree with Herb Sutter's recommendation that (assuming the
>> class or struct has some member functions) data members should
>> never be public.  There are cases where for data members might
>> plausibly be made protected rather than private, but never
>> public.
>
> There is a case where a data member is safe to be public:  a const
> data member.  Access to such a member cannot change a class's
> invariants.

My experience with const data members is that they are almost
always more trouble than they're worth.  Even in those cases
where a data member is made const, it's better to stick to the
simple rule that data members (other than pure structs) never be
public, on general principles of information hiding:  client code
shouldn't know or care what particular data members a class has,
let alone whether they are const or not.  Any property an object
wants to supply to its clients should be made available through a
(usually const) member function, and only that, regardless of
whether the property needs an elaborate computation or is simply
returning the value of a data member -- even a const one.

[toc] | [prev] | [next] | [standalone]


#67914

FromMelzzzzz <Melzzzzz@zzzzz.com>
Date2019-08-23 18:07 +0000
Message-ID<LXV7F.35440$hJ3.16176@fx07.am4>
In reply to#67897
On 2019-08-23, Ian Collins <ian-news@hotmail.com> wrote:
> On 23/08/2019 10:09, Tim Rentsch wrote:
>> JiiPee <no@notvalid.com> writes:
>> 
>> [some white space reformatting done]
>> 
>>> Which one is better:  1)
>>>
>>>      class Person {
>>>        public:
>>>          int getAge() { return age;}
>>>          void setAge(int a) { age = a;}
>>>        private:
>>>          int age;
>>>      };
>>>
>>> or  2)
>>>
>>>      struct Person {
>>>          int age;
>>>      };
>>>
>>> ####
>>>
>>> I know Herb Sutter recommended 1) but for example isocpp
>>>
>>> https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rh-get
>>>
>>> seems to recommend 2). [...]
>>>
>>> I do currently 1) but wondering which way to go.
>>>
>>> Like now I have a "Settings" class.  Simple data members.  I started
>>> adding getters and setters....
>> 
>> I agree with Herb Sutter's recommendation that (assuming the
>> class or struct has some member functions) data members should
>> never be public.  There are cases where for data members might
>> plausibly be made protected rather than private, but never
>> public.
>
> There is a case where a data member is safe to be public:  a const data 
> member.  Access to such a member cannot change a class's invariants.
>
Also there is case when member is class with own interface.


-- 
press any key to continue or any other to quit...
U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec
Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi 
bili naoruzani. -- Mladen Gogala

[toc] | [prev] | [next] | [standalone]


#67899

FromJiiPee <no@notvalid.com>
Date2019-08-23 07:09 +0100
Message-ID<SqL7F.98411$WI2.78457@fx34.am4>
In reply to#67890
On 22/08/2019 23:09, Tim Rentsch wrote:
> (Incidentally I am ignoring the "age/birthday" matter
> that some other people have commented on, and assuming your
> question is meant as generic, with 'age' being merely an
> unfortunate choice of example.)


correct. the example given might not have been the best. general 
question about all situations.


>
> I suggest however a slightly different pattern than (1), along
> these lines (disclaimer: not compiled):
>
>      class Person {
>          unsigned siblings_;
>          // ... other data members ...
>
>        public:
>          // ... other member functions
>
>                unsigned &siblings()       { return siblings_; }
>          const unsigned &siblings() const { return siblings_; }
>      };
>
> Now our accessor functions look more like data member access, but
> they remain functions:
>
>      if(  fred.siblings() > 0  )  ...
>
>      fred.siblings() += 1;  // a new birth in fred's family
>
> To me this pattern reads nicer on the client side than set/get
> functions.


yes many seems to suggest this online


[toc] | [prev] | [next] | [standalone]


#67900

FromJiiPee <no@notvalid.com>
Date2019-08-23 07:13 +0100
Message-ID<0uL7F.49321$Xs5.2002@fx06.am4>
In reply to#67849
On 22/08/2019 23:22, Stefan Ram wrote:
> Instead of asking the object for data and the processing
>    to data outside of the object (as when using accessors),
>    you should tell the object to do the processing itself.


sometimes its about storing global settings like:

struct Settings

{

Color backgroundColor;

int fontSize;

....

};


So I guess this class is not really meant to operate with the values 
only return them? it just bundless a group of data.

[toc] | [prev] | [next] | [standalone]


#67901

FromDavid Brown <david.brown@hesbynett.no>
Date2019-08-23 09:30 +0200
Message-ID<qjo4mm$g40$1@dont-email.me>
In reply to#67900
On 23/08/2019 08:13, JiiPee wrote:
> On 22/08/2019 23:22, Stefan Ram wrote:
>> Instead of asking the object for data and the processing
>>    to data outside of the object (as when using accessors),
>>    you should tell the object to do the processing itself.
> 
> 
> sometimes its about storing global settings like:
> 
> struct Settings
> 
> {
> 
> Color backgroundColor;
> 
> int fontSize;
> 
> ....
> 
> };
> 
> 
> So I guess this class is not really meant to operate with the values
> only return them? it just bundless a group of data.
> 

Classes like that still need to have protection.  There may not be need
for synchronisation between members for keeping invariants, but usually
you don't want to allow any possibility of other parts of the code
making uncoordinated changes to the values.

[toc] | [prev] | [next] | [standalone]


#67930

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-08-25 06:16 +0000
Message-ID<slrnqm49ua.cdo.grahn+nntp@frailea.sa.invalid>
In reply to#67901
On Fri, 2019-08-23, David Brown wrote:
> On 23/08/2019 08:13, JiiPee wrote:
>> On 22/08/2019 23:22, Stefan Ram wrote:
>>> Instead of asking the object for data and the processing
>>>    to data outside of the object (as when using accessors),
>>>    you should tell the object to do the processing itself.
>> 
>> 
>> sometimes its about storing global settings like:
>> 
>> struct Settings
>> {
>> Color backgroundColor;
>> int fontSize;
>> ....
>> };
>> 
>> So I guess this class is not really meant to operate with the values
>> only return them? it just bundless a group of data.
>> 
>
> Classes like that still need to have protection.  There may not be need
> for synchronisation between members for keeping invariants, but usually
> you don't want to allow any possibility of other parts of the code
> making uncoordinated changes to the values.

Personally, for a config struct I'd ask myself "will I create this
object early and pass it once to the main application logic?".  If the
answer is 'yes', I'd happily pass it as const and leave it as it is.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#67934

FromDavid Brown <david.brown@hesbynett.no>
Date2019-08-25 12:12 +0200
Message-ID<qjtmva$r9t$2@dont-email.me>
In reply to#67930
On 25/08/2019 08:16, Jorgen Grahn wrote:
> On Fri, 2019-08-23, David Brown wrote:
>> On 23/08/2019 08:13, JiiPee wrote:
>>> On 22/08/2019 23:22, Stefan Ram wrote:
>>>> Instead of asking the object for data and the processing
>>>>    to data outside of the object (as when using accessors),
>>>>    you should tell the object to do the processing itself.
>>>
>>>
>>> sometimes its about storing global settings like:
>>>
>>> struct Settings
>>> {
>>> Color backgroundColor;
>>> int fontSize;
>>> ....
>>> };
>>>
>>> So I guess this class is not really meant to operate with the values
>>> only return them? it just bundless a group of data.
>>>
>>
>> Classes like that still need to have protection.  There may not be need
>> for synchronisation between members for keeping invariants, but usually
>> you don't want to allow any possibility of other parts of the code
>> making uncoordinated changes to the values.
> 
> Personally, for a config struct I'd ask myself "will I create this
> object early and pass it once to the main application logic?".  If the
> answer is 'yes', I'd happily pass it as const and leave it as it is.
> 

That could well be sufficient protection, yes.

[toc] | [prev] | [next] | [standalone]


#67902

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-08-23 11:24 +0000
Message-ID<slrnqlvj7n.cdo.grahn+nntp@frailea.sa.invalid>
In reply to#67849
On Thu, 2019-08-22, Stefan Ram wrote:
> Supersedes: <accessor-20190822232107@ram.dialup.fu-berlin.de>
> [Typos and clarifications]
>
> JiiPee <no@notvalid.com> writes:
>>int age;

>   A class needs to protect its invariants. 
>
>   Therefore, a member can be public only if it is not
>   mentioned in an invariant of the class.

I think invariants (explicit or implicit) is why setters and getters
bother me.

Either you have a C struct with no invariants, and setters/getters are
just unnecessary OO noise on top of non-OO code.

Or you /do/ have invariants, and setting an individual member, at any
time, threatens to break the invariant.  Which doesn't mean there can
be /no/ set/get methods, they won't map 1:1 to the members.

>   An accessor, however, is just appropriate for data
>   classes where objects effectively are used to represent
>   records as in non-OOP programming. In OOP they violate
>   "Tell, Don't Ask!".
>
>   Instead of asking the object for data and then processing
>   the data outside of the object (as when using accessors),
>   you should just /tell the object/ to do the processing.

Moving logic into the class instead of treating it like a dumb
container.  Also good advice (except of course when you /want/
a dumb container).

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#67905

FromJames Kuyper <jameskuyper@alumni.caltech.edu>
Date2019-08-23 08:34 -0400
Message-ID<qjomgf$dtc$1@dont-email.me>
In reply to#67902
On 8/23/19 7:24 AM, Jorgen Grahn wrote:
...
> I think invariants (explicit or implicit) is why setters and getters
> bother me.
> 
> Either you have a C struct with no invariants, and setters/getters are
> just unnecessary OO noise on top of non-OO code.
> 
> Or you /do/ have invariants, and setting an individual member, at any
> time, threatens to break the invariant.  Which doesn't mean there can
> be /no/ set/get methods, they won't map 1:1 to the members.

In general, I agree. However, a setter for a single member could make
sense, if the applicable constraints allow two or more different values
for that member, even if all other members are unchanged. For instance,
the invariant might be current_value <= maximum_achieved_value. The
setter for current_value would deal with changes that would violate that
invariant, either by rejecting them or by increasing
maximum_achieved_value (which corresponds to the last case you mention:
a setter that changes two or more members in synchrony).

[toc] | [prev] | [next] | [standalone]


#67910

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-08-23 14:48 +0000
Message-ID<slrnqlvv5t.cdo.grahn+nntp@frailea.sa.invalid>
In reply to#67905
On Fri, 2019-08-23, Stefan Ram wrote:
> James Kuyper <jameskuyper@alumni.caltech.edu> writes:
>>On 8/23/19 7:24 AM, Jorgen Grahn wrote:
>>>Or you /do/ have invariants, and setting an individual member, at any
>>>time, threatens to break the invariant.  Which doesn't mean there can
>>>be /no/ set/get methods, they won't map 1:1 to the members.
> ..
>>invariant, either by rejecting them or by increasing
>>maximum_achieved_value (which corresponds to the last case you mention:
>>a setter that changes two or more members in synchrony).

When I wrote "map 1:1 to the members" I was more thinking of someone
going through all the members and adding a setter for each of them.

>   Behind all of this lurks the question: How does one define "setter"?

How about "a method that's defined in terms of changing a certain part
of the object, without considering the object as one single entity"?

But I suppose that's my definition of a setter I dislike, rather than
of all setters.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [next] | [standalone]


#67911

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2019-08-23 15:49 +0000
Message-ID<slrnqm02np.cdo.grahn+nntp@frailea.sa.invalid>
In reply to#67905
On Fri, 2019-08-23, James Kuyper wrote:
> On 8/23/19 7:24 AM, Jorgen Grahn wrote:
> ...
>> I think invariants (explicit or implicit) is why setters and getters
>> bother me.
>> 
>> Either you have a C struct with no invariants, and setters/getters are
>> just unnecessary OO noise on top of non-OO code.
>> 
>> Or you /do/ have invariants, and setting an individual member, at any
>> time, threatens to break the invariant.  Which doesn't mean there can
>> be /no/ set/get methods, they won't map 1:1 to the members.
>
> In general, I agree. However, a setter for a single member could make
> sense, if the applicable constraints allow two or more different values
> for that member, even if all other members are unchanged. For instance,
> the invariant might be current_value <= maximum_achieved_value. The
> setter for current_value would deal with changes that would violate that
> invariant, either by rejecting them or by increasing
> maximum_achieved_value (which corresponds to the last case you mention:
> a setter that changes two or more members in synchrony).

I can imagine how that could end up with me breaking out:

   ValueWithHighwatermark<int> foo = 2; // 2, 2
   foo = 3; // 3, 3
   foo = 0; // 0, 3

I know it was just an example, but my gut feeling is that there
are often solutions like that: to raise the abstraction level
of the members.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web