Good chained function name?

Discussion in 'C++' started by Nephi Immortal, Feb 14, 2013.

  1. I ask you for your opinion what chained function name look like. I do not need to post class definition since you know what I am talking about.

    Let’s say for example I have 'A' class.

    A a( 1 ), b( 2 ), c( 3 );
    int data = a.get_value();
    a.set_value( 2 );

    What if I am going to write like this below?

    a.set_value( b.get_value() + c.get_value() );

    They can be to include operator=, operator+, and operator cast. It looksvery readable than getter and setter.

    a = b + c;

    What if I choose to use chained function name?

    a.value() = b.value() + c.value();

    Is that readable?

    If I name value1() and value2(), I may not want to place them in the main class. I rather prefer to place them in the nested class.

    a.Inner().value1() = b.Inner().value1() + c.Inner().value2();

    What if I don’t like “Inner()”? It should be removed and operator()() is used.

    a().value1() = b().value1() + c().value2();

    Do chained function name sound good?

    Let’s give some ideas.

    int data1, data2, data3;

    data1 = a.Get().Bytes();
    data2 = b.Get().Kilobytes();
    data3 = c.Get().Megabytes();

    a.Set().Bytes( 1 );
    b.Set().Kilobytes( 2 );
    c.Set().Megabytes( 3 );

    data1 = a().Bytes();
    data2 = b().Kilobytes();
    data3 = c().Megabytes();

    a().Bytes() = 1;
    b().Kilobytes() = 2;
    c().Megabytes() = 3;

    a().Bytes() = b().Kilobytes() + c().Megabytes();

    Please comment if my code looks readable.
    Nephi Immortal, Feb 14, 2013
    #1
    1. Advertising

  2. On 2/13/2013 11:43 PM, Nephi Immortal wrote:
    > I ask you for your opinion what chained function name look like. I
    > do

    not need to post class definition since you know what I am talking about.
    >
    > Let’s say for example I have 'A' class.
    >
    > A a( 1 ), b( 2 ), c( 3 );
    > int data = a.get_value();
    > a.set_value( 2 );
    >
    > What if I am going to write like this below?
    >
    > a.set_value( b.get_value() + c.get_value() );


    <shrug> I've seen it done.

    > They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.
    >
    > a = b + c;


    Looks OK to me, as well. Supposedly, the type A is a "value type" that
    defines addition as one of its operations.

    > What if I choose to use chained function name?


    Never heard this term, so not sure what the meaning of it is.

    >
    > a.value() = b.value() + c.value();
    >
    > Is that readable?


    Readability is subjective. To me it's no more readable than a=b+c. Of
    course, if each A has different, independently settable values, then it
    would make sense to separate them by means of their own accessors.

    a.value_blah() = b.value_blah() * c.value_droo();

    > If I name value1() and value2(), I may not want to place them in the

    main class. I rather prefer to place them in the nested class.
    >
    > a.Inner().value1() = b.Inner().value1() + c.Inner().value2();


    I don't see any reason to do so.

    > What if I don’t like “Inner()� It should be removed and operator()() is used.
    >
    > a().value1() = b().value1() + c().value2();
    >
    > Do chained function name sound good?


    What's "chained function"?

    > Let’s give some ideas.
    >
    > int data1, data2, data3;
    >
    > data1 = a.Get().Bytes();
    > data2 = b.Get().Kilobytes();
    > data3 = c.Get().Megabytes();
    >
    > a.Set().Bytes( 1 );
    > b.Set().Kilobytes( 2 );
    > c.Set().Megabytes( 3 );
    >
    > data1 = a().Bytes();
    > data2 = b().Kilobytes();
    > data3 = c().Megabytes();
    >
    > a().Bytes() = 1;
    > b().Kilobytes() = 2;
    > c().Megabytes() = 3;
    >
    > a().Bytes() = b().Kilobytes() + c().Megabytes();
    >
    > Please comment if my code looks readable.


    Since the type of 'Bytes', etc., is all the same, it seems to be OK to
    add them together. It's not proper from the POV of dimensioned values,
    though. In this particular case 'Bytes' and 'Kilobytes' don't look good
    as function names, but rather dimensioned types. "Storage", "Volume",
    or "Capacity", are better names. Whether the values returned by those
    functions are in bytes or kilobytes, can be easily decided, and then you
    can easily add those together to yield a value of the more granulated
    type, IOW if bytes and kilobytes are added, you get bytes in which
    kilobytes are multiplied correspondingly.

    So, in short, no, I don't think your code is readable because it does
    not reflect anything that would make sense to me. But, again, it can be
    all in the eye of the beholder. If you don't intend your code to be
    read by anybody else but you, make it readable to *you*, nothing else is
    of any importance.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 14, 2013
    #2
    1. Advertising

  3. Nephi Immortal

    Öö Tiib Guest

    On Thursday, 14 February 2013 06:43:24 UTC+2, Nephi Immortal wrote:
    > I ask you for your opinion what chained function name look like.
    > I do not need to post class definition since you know what I am talking about.



    We can imagine how to achieve that.

    > Let’s say for example I have 'A' class.
    >
    > A a( 1 ), b( 2 ), c( 3 );
    >
    > int data = a.get_value();
    > a.set_value( 2 );
    >
    > What if I am going to write like this below?
    >
    > a.set_value( b.get_value() + c.get_value() );


    You see yourself that it is too much code bloat. Viewing classes as storage
    of values of other types is common but too primitive usage. It
    exposes internals and makes error handling hard.

    > They can be to include operator=, operator+, and operator cast. It
    > looks very readable than getter and setter.
    >
    > a = b + c;


    Yes, that is done often and is good. Full externally observable "value" of
    instance participates (we call it "state"). That state is usually not
    representable as single value of some simpler type (like int) that you can
    "get".

    > What if I choose to use chained function name?
    >
    > a.value() = b.value() + c.value();


    If that value is full state, then previous was better. If it is some property
    then setter feels wrong, getters look fine:

    a.length() = b.length() + c.length(); // worse
    a.resize( b.length() + c.length() ); // better

    > Is that readable?
    >
    > If I name value1() and value2(), I may not want to place them in the
    > main class. I rather prefer to place them in the nested class.
    >
    > a.Inner().value1() = b.Inner().value1() + c.Inner().value2();


    Now you expose internals of internals, that endangers your design to grow
    into terrible spaghetti.

    > What if I don’t like “Inner()”? It should be removed and operator()() is
    > used.
    >
    > a().value1() = b().value1() + c().value2();


    Unreadable. Confusing usage of function call operator. Reserve function
    call operator for objects that behave like functions.

    > Do chained function name sound good?
    >
    > Let’s give some ideas.
    >
    > int data1, data2, data3;
    >
    > data1 = a.Get().Bytes();
    > data2 = b.Get().Kilobytes();
    > data3 = c.Get().Megabytes();
    > a.Set().Bytes( 1 );
    > b.Set().Kilobytes( 2 );
    > c.Set().Megabytes( 3 );
    > data1 = a().Bytes();
    > data2 = b().Kilobytes();
    > data3 = c().Megabytes();
    > a().Bytes() = 1;
    > b().Kilobytes() = 2;
    > c().Megabytes() = 3;


    I like none. These are names of units of measurement otherwise plural names
    feel like container accessors for me.

    Use 'discA.size().asKiloBytes()' ... or actually I don't understand your
    example. Try to come up with examples closer to practice.

    > a().Bytes() = b().Kilobytes() + c().Megabytes();
    >
    > Please comment if my code looks readable.


    Adding kilobytes to megabytes and getting bytes? It feels as readable as
    any too obvious logic error can be. If I read it I feel that either I don't
    understand something major or it is unbelievably wrong. I am confused by
    such code.
    Öö Tiib, Feb 14, 2013
    #3
  4. Nephi Immortal

    Stefan Ram Guest

    Öö Tiib <> writes:
    > a.length() = b.length() + c.length(); // worse
    > a.resize( b.length() + c.length() ); // better


    Should be

    a.length( b.length() + c.length() )

    according with the standard library:

    const int prec = ::std::cout.precision();
    ::std::cout.precision( prec );
    Stefan Ram, Feb 14, 2013
    #4
  5. On 2/14/2013 8:14 AM, Stefan Ram wrote:
    > Öö Tiib <> writes:
    >> a.length() = b.length() + c.length(); // worse
    >> a.resize( b.length() + c.length() ); // better

    >
    > Should be
    >
    > a.length( b.length() + c.length() )
    >
    > according with the standard library:
    >
    > const int prec = ::std::cout.precision();
    > ::std::cout.precision( prec );
    >
    > .


    The Standard library is but an example of a committee's understanding of
    readability. And we know quite well what a horse designed by a
    committee looks like. Choosing a noun to also play the role of setting
    the value (along with getting it) is not the best approach to concur
    readability IMNSHO. Of course to many whose native tongue is not
    English it might not matter (no offense is intended). After all, it's
    an idiom. The case like this ('blah' without an argument is a getter,
    and 'blah' *with an argument* is a setter) might be one case where C++
    overloading shines, but I'm reminded that all that glitters is not gold.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 14, 2013
    #5
  6. Nephi Immortal

    Öö Tiib Guest

    On Thursday, 14 February 2013 15:14:34 UTC+2, Stefan Ram wrote:
    > �� Tiib <> writes:
    > > a.length() = b.length() + c.length(); // worse
    > > a.resize( b.length() + c.length() ); // better

    >
    > Should be
    >
    > a.length( b.length() + c.length() )
    >
    > according with the standard library:
    >
    > const int prec = ::std::cout.precision();
    > ::std::cout.precision( prec );


    Standard library is pile of subtle inconsistencies that can't me edited
    because of backward compatibility. The input/output library is notably
    different from rest of it AND it is the part that is most frequently
    bashed for inefficiency and inconvenience. Less bashed container library
    is more consistent with what I wrote:

    typedef std::vector<int> Ints;
    Ints a( 3, 7 );
    Ints b( 5 );
    Ints c;

    // properties are changed with operations whose name is verb, not noun
    c.resize( a.size() + b.capacity() );
    c.shrink_to_fit();
    // accessors to non-properties are nouns providing references
    c.front() = 42;
    Öö Tiib, Feb 14, 2013
    #6
  7. Nephi Immortal

    Jeff Flinn Guest

    On 2/13/2013 11:43 PM, Nephi Immortal wrote:
    > I ask you for your opinion what chained function name look like. I do not need to post class definition since you know what I am talking about.
    >
    > Let’s say for example I have 'A' class.
    >
    > A a( 1 ), b( 2 ), c( 3 );
    > int data = a.get_value();
    > a.set_value( 2 );
    >
    > What if I am going to write like this below?
    >
    > a.set_value( b.get_value() + c.get_value() );
    >
    > They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.
    >
    > a = b + c;
    >
    > What if I choose to use chained function name?
    >
    > a.value() = b.value() + c.value();
    >
    > Is that readable?


    Well, the function named 'value' would lead me to believe that it, well
    returns by value, and not by reference. So I would expect the above
    expression to have no lasting effect as the temporary returned by value
    gets it's value set, and then is gone at the ;

    Jeff
    Jeff Flinn, Feb 14, 2013
    #7
  8. On 2/14/2013 8:47 AM, Jeff Flinn wrote:
    > On 2/13/2013 11:43 PM, Nephi Immortal wrote:
    >> I ask you for your opinion what chained function name look like. I do
    >> not need to post class definition since you know what I am talking about.
    >>
    >> Let’s say for example I have 'A' class.
    >>
    >> A a( 1 ), b( 2 ), c( 3 );
    >> int data = a.get_value();
    >> a.set_value( 2 );
    >>
    >> What if I am going to write like this below?
    >>
    >> a.set_value( b.get_value() + c.get_value() );
    >>
    >> They can be to include operator=, operator+, and operator cast. It
    >> looks very readable than getter and setter.
    >>
    >> a = b + c;
    >>
    >> What if I choose to use chained function name?
    >>
    >> a.value() = b.value() + c.value();
    >>
    >> Is that readable?

    >
    > Well, the function named 'value' would lead me to believe that it, well
    > returns by value, and not by reference. So I would expect the above
    > expression to have no lasting effect as the temporary returned by value
    > gets it's value set, and then is gone at the ;


    So, would you then recommend to have a 'reference' as a function name,
    as in

    a.reference() = b.value() + c.value();

    ? 8-[

    May I remind you that 'value' *can* mean an L-value just as much as an
    R-value? Especially when it appears on the *L*eft side of the
    assignment... Just sayin'... ;-)

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 14, 2013
    #8
  9. Nephi Immortal

    Jeff Flinn Guest

    On 2/14/2013 8:52 AM, Victor Bazarov wrote:
    > On 2/14/2013 8:47 AM, Jeff Flinn wrote:
    >> On 2/13/2013 11:43 PM, Nephi Immortal wrote:
    >>> I ask you for your opinion what chained function name look like. I do
    >>> not need to post class definition since you know what I am talking
    >>> about.
    >>>
    >>> Let’s say for example I have 'A' class.
    >>>
    >>> A a( 1 ), b( 2 ), c( 3 );
    >>> int data = a.get_value();
    >>> a.set_value( 2 );
    >>>
    >>> What if I am going to write like this below?
    >>>
    >>> a.set_value( b.get_value() + c.get_value() );
    >>>
    >>> They can be to include operator=, operator+, and operator cast. It
    >>> looks very readable than getter and setter.
    >>>
    >>> a = b + c;
    >>>
    >>> What if I choose to use chained function name?
    >>>
    >>> a.value() = b.value() + c.value();
    >>>
    >>> Is that readable?

    >>
    >> Well, the function named 'value' would lead me to believe that it, well
    >> returns by value, and not by reference. So I would expect the above
    >> expression to have no lasting effect as the temporary returned by value
    >> gets it's value set, and then is gone at the ;

    >
    > So, would you then recommend to have a 'reference' as a function name,
    > as in
    >
    > a.reference() = b.value() + c.value();
    >
    > ? 8-[


    I would avoid the whole approach. I'm assuming the OP's example is just
    that: a paired down example. Without a clearer def of the class in
    question it's difficult to say what approach should be used, indeed are
    these accessor/mutator pairs even needed.

    Jeff
    Jeff Flinn, Feb 14, 2013
    #9
  10. Nephi Immortal

    Öö Tiib Guest

    On Thursday, 14 February 2013 16:27:29 UTC+2, Jeff Flinn wrote:
    > On 2/14/2013 8:52 AM, Victor Bazarov wrote:
    > > On 2/14/2013 8:47 AM, Jeff Flinn wrote:
    > >> On 2/13/2013 11:43 PM, Nephi Immortal wrote:
    > >>> What if I choose to use chained function name?
    > >>>
    > >>> a.value() = b.value() + c.value();
    > >>>
    > >>> Is that readable?
    > >>
    > >> Well, the function named 'value' would lead me to believe that it, well
    > >> returns by value, and not by reference. So I would expect the above
    > >> expression to have no lasting effect as the temporary returned by value
    > >> gets it's value set, and then is gone at the ;

    > >
    > > So, would you then recommend to have a 'reference' as a function name,
    > > as in
    > >
    > > a.reference() = b.value() + c.value();
    > >
    > > ? 8-[

    >
    > I would avoid the whole approach. I'm assuming the OP's example is just
    > that: a paired down example. Without a clearer def of the class in
    > question it's difficult to say what approach should be used, indeed are
    > these accessor/mutator pairs even needed.


    Try to be more constructive? Your answer feels like Nephi should just
    drop dead and stop trying. It is easy to imagine something what can be
    under question. Then naming can be discussed. I try to demonstrate:

    'value' (as noun) can not be considered non-property of something whose
    'value' it is. I never provide properties as L-Values for any by-passer
    to store references at and change at will. I feel it error-prone.

    I prefer immutable (after construction) properties. I feel it is safer
    It can be LOT more efficient if property's value is even set
    compile-time. Consider such things about every property.

    If there is certain need to mutate a property during object's life-time
    then it deserves command-like operations named by verbs. It is better
    to make such operations as safe and complete as possible. Keep invariant
    of whole object under its own control.

    'value' is still hard example since it is fitting verb too. On such cases
    I prefer to use some synonymous verb (like 'assess', 'estimate', 'evaluate')
    to reduce the possible confusion:

    a.revalue( b.price() + c.net_value() );
    Öö Tiib, Feb 14, 2013
    #10
  11. On 2/14/2013 10:14 AM, Öö Tiib wrote:
    > [..]
    > 'value' (as noun) can not be considered non-property of something whose
    > 'value' it is. I never provide properties as L-Values for any by-passer
    > to store references at and change at will. I feel it error-prone.
    >
    > I prefer immutable (after construction) properties. I feel it is safer
    > It can be LOT more efficient if property's value is even set
    > compile-time. Consider such things about every property.
    >
    > If there is certain need to mutate a property during object's life-time
    > then it deserves command-like operations named by verbs. It is better
    > to make such operations as safe and complete as possible. Keep invariant
    > of whole object under its own control.
    >
    > 'value' is still hard example since it is fitting verb too. On such cases
    > I prefer to use some synonymous verb (like 'assess', 'estimate', 'evaluate')
    > to reduce the possible confusion:
    >
    > a.revalue( b.price() + c.net_value() );


    Uh... Perhaps it's a wrong path we're trying to follow. 'Price' is a
    verb as well as a noun, 'estimate' is a noun as well as a verb... :)

    There is something to be said about 'set' as well (it's a noun too, I am
    sure you've heard of 'std::set' :*)), but in combination with another
    word it is less likely to be confused. I would definitely prefer
    'set_value' to 'revalue' (along with 'value' as a "get"-like accessor).
    But that's just me. Keep in mind that readability is still
    subjective, let's not try to deceive *ourselves* into thinking that
    there can be a complete set of readability rules suitable for everybody.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 14, 2013
    #11
  12. Nephi Immortal

    Luca Risolia Guest

    On 14/02/2013 05:43, Nephi Immortal wrote:
    > I ask you for your opinion what chained function name look like. I do not need to post class definition since you know what I am talking about.
    >
    > Let’s say for example I have 'A' class.
    >
    > A a( 1 ), b( 2 ), c( 3 );
    > int data = a.get_value();
    > a.set_value( 2 );
    >
    > What if I am going to write like this below?
    >
    > a.set_value( b.get_value() + c.get_value() );
    >
    > They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.
    >
    > a = b + c;
    >
    > What if I choose to use chained function name?
    >
    > a.value() = b.value() + c.value();
    >
    > Is that readable?
    >
    > If I name value1() and value2(), I may not want to place them in the main class. I rather prefer to place them in the nested class.
    >
    > a.Inner().value1() = b.Inner().value1() + c.Inner().value2();
    >
    > What if I don’t like “Inner()”? It should be removed and operator()() is used.
    >
    > a().value1() = b().value1() + c().value2();
    >
    > Do chained function name sound good?
    >


    "a = b + c" looks good. All the other alternatives are more difficult to
    read.

    > Let’s give some ideas.
    >
    > int data1, data2, data3;
    >
    > data1 = a.Get().Bytes();
    > data2 = b.Get().Kilobytes();
    > data3 = c.Get().Megabytes();
    >
    > a.Set().Bytes( 1 );
    > b.Set().Kilobytes( 2 );
    > c.Set().Megabytes( 3 );
    >
    > data1 = a().Bytes();
    > data2 = b().Kilobytes();
    > data3 = c().Megabytes();
    >
    > a().Bytes() = 1;
    > b().Kilobytes() = 2;
    > c().Megabytes() = 3;
    >
    > a().Bytes() = b().Kilobytes() + c().Megabytes();
    >
    > Please comment if my code looks readable.


    I think it is not readable. It's not type-safe for sure, which makes
    your code error-prone. You might loose your spacecraft in the space.

    I would suggest a more modern and safe approach, for example:

    #include <iostream>

    template<int UB, int US>
    struct Unit { // a unit in the SI/IEEE systems
    enum { B=UB, s=US }; // bytes and seconds
    };

    template<typename Unit> // a magnitude with a unit
    struct Value {
    double val; // the magnitude
    explicit constexpr Value(double d) : val(d) {} // construct a Value
    from a double
    // other constructors...
    Value operator+(const Value& x) {
    return Value(val + x.val);
    }
    };

    using Byte = Unit<1, 0>; // unit: byte
    using MemBlock = Value<Byte>; // shortcut

    constexpr Value<Byte> operator"" _B(long double d) {
    return Value<Byte> (d);
    }

    constexpr Value<Byte> operator"" _kB(long double d) {
    return Value<Byte> (d * 1024);
    }

    constexpr Value<Byte> operator"" _MB(long double d) {
    return Value<Byte> (d * 1024 * 1024);
    }

    constexpr double to_B(const Value<Byte>& b) { // free functions to be simple
    return b.val;
    }

    constexpr double to_kB(const Value<Byte>& b) {
    return b.val / 1024;
    }

    constexpr double to_MB(const Value<Byte>& b) {
    return b.val / 1024 / 1024;
    }

    // Let's add something useful to the example
    using Second = Unit<0, 1>; // unit: sec.
    // using Second2 = Unit<0, 2>; // s^2
    using Time = Value<Second>; // time in seconds by default
    using TransferRate = Value<Unit<1, -1>>; // bytes/second type

    constexpr Value<Second> operator"" _s(long double d) {
    return Value<Second> (d);
    }

    constexpr double to_s(const Value<Second>& s) {
    return s.val;
    }

    constexpr TransferRate operator/(const MemBlock& m, const Time& s) {
    return TransferRate(to_B(m) / to_s(s));
    }

    int main() {
    MemBlock a = 1024.0_B;
    //MemBlock b = 3.0; // NOT OK! unit needed
    auto b = 3.0_kB; // OK
    auto c = a + b;
    std::cout << to_kB(a) << "+" << to_kB(b)
    << " = " << to_kB(c) << '\n'; // or define your operator<<()

    // Another example..
    TransferRate slow = c / 1.0_s;
    auto fast = slow + slow;
    // etc..
    }
    Luca Risolia, Feb 14, 2013
    #12
  13. On Thursday, February 14, 2013 5:59:55 AM UTC-6, Victor Bazarov wrote:
    > On 2/13/2013 11:43 PM, Nephi Immortal wrote:
    >
    > > I ask you for your opinion what chained function name look like. I

    >
    > > do

    >
    > not need to post class definition since you know what I am talking about.
    >
    > >

    >
    > > Let’s say for example I have 'A' class.

    >
    > >

    >
    > > A a( 1 ), b( 2 ), c( 3 );

    >
    > > int data = a.get_value();

    >
    > > a.set_value( 2 );

    >
    > >

    >
    > > What if I am going to write like this below?

    >
    > >

    >
    > > a.set_value( b.get_value() + c.get_value() );

    >
    >
    >
    > <shrug> I've seen it done.
    >
    >
    >
    > > They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.

    >
    > >

    >
    > > a = b + c;

    >
    >
    >
    > Looks OK to me, as well. Supposedly, the type A is a "value type" that
    >
    > defines addition as one of its operations.
    >
    >
    >
    > > What if I choose to use chained function name?

    >
    >
    >
    > Never heard this term, so not sure what the meaning of it is.


    Hi Victor--please see my comments below.

    >
    >
    >
    > >

    >
    > > a.value() = b.value() + c.value();

    >
    > >

    >
    > > Is that readable?

    >
    >
    >
    > Readability is subjective. To me it's no more readable than a=b+c. Of
    >
    > course, if each A has different, independently settable values, then it
    >
    > would make sense to separate them by means of their own accessors.
    >
    >
    >
    > a.value_blah() = b.value_blah() * c.value_droo();
    >
    >
    >
    > > If I name value1() and value2(), I may not want to place them in the

    >
    > main class. I rather prefer to place them in the nested class.
    >
    > >

    >
    > > a.Inner().value1() = b.Inner().value1() + c.Inner().value2();

    >
    >
    >
    > I don't see any reason to do so.
    >
    >
    >
    > > What if I don’t like “Inner()”? It should be removed and operator()() is used.

    >
    > >

    >
    > > a().value1() = b().value1() + c().value2();

    >
    > >

    >
    > > Do chained function name sound good?

    >
    >
    >
    > What's "chained function"?


    See my comment here.

    "chained function" mean putting two or more functions together
    into one line like this below.

    A a;

    a().func1().func2(0.func3().etc();

    Inner() is nested class. Inner() is in main class to be called and return
    Inner class type before chained functions in Inner class can be used.
    Inner() can be replaced to operator()().

    >
    >
    >
    > > Let’s give some ideas.

    >
    > >

    >
    > > int data1, data2, data3;

    >
    > >

    >
    > > data1 = a.Get().Bytes();

    >
    > > data2 = b.Get().Kilobytes();

    >
    > > data3 = c.Get().Megabytes();

    >
    > >

    >
    > > a.Set().Bytes( 1 );

    >
    > > b.Set().Kilobytes( 2 );

    >
    > > c.Set().Megabytes( 3 );

    >
    > >

    >
    > > data1 = a().Bytes();

    >
    > > data2 = b().Kilobytes();

    >
    > > data3 = c().Megabytes();

    >
    > >

    >
    > > a().Bytes() = 1;

    >
    > > b().Kilobytes() = 2;

    >
    > > c().Megabytes() = 3;

    >
    > >

    >
    > > a().Bytes() = b().Kilobytes() + c().Megabytes();

    >
    > >

    >
    > > Please comment if my code looks readable.

    >
    >
    >
    > Since the type of 'Bytes', etc., is all the same, it seems to be OK to
    >
    > add them together. It's not proper from the POV of dimensioned values,
    >
    > though. In this particular case 'Bytes' and 'Kilobytes' don't look good
    >
    > as function names, but rather dimensioned types. "Storage", "Volume",
    >
    > or "Capacity", are better names. Whether the values returned by those
    >
    > functions are in bytes or kilobytes, can be easily decided, and then you
    >
    > can easily add those together to yield a value of the more granulated
    >
    > type, IOW if bytes and kilobytes are added, you get bytes in which
    >
    > kilobytes are multiplied correspondingly.


    You can create several classes like this below.

    class Byte;
    class Kilobyte;
    class Megabyte;
    ....
    ....

    Byte, Kilobyte and Megabyte are different types.

    What if I show this below?

    a().Kilobytes() = b().Bytes + c().Megabytes;

    b().Bytes will be converted to Kilobytes by dividing 1024 bytes and
    c().Megabytes will be converted to Kilobytes by multiplying 1024 bytes
    before the result is to be Kilobyte value.


    >
    >
    >
    > So, in short, no, I don't think your code is readable because it does
    >
    > not reflect anything that would make sense to me. But, again, it can be
    >
    > all in the eye of the beholder. If you don't intend your code to be
    >
    > read by anybody else but you, make it readable to *you*, nothing else is
    >
    > of any importance.
    >
    >
    >
    > V
    >
    > --
    >
    > I do not respond to top-posted replies, please don't ask
    Nephi Immortal, Feb 14, 2013
    #13
  14. Nephi Immortal

    Jorgen Grahn Guest

    On Thu, 2013-02-14, Öö Tiib wrote:
    > On Thursday, 14 February 2013 16:27:29 UTC+2, Jeff Flinn wrote:

    ....
    >> I would avoid the whole approach. I'm assuming the OP's example is just
    >> that: a paired down example. Without a clearer def of the class in
    >> question it's difficult to say what approach should be used, indeed are
    >> these accessor/mutator pairs even needed.

    >
    > Try to be more constructive? Your answer feels like Nephi should just
    > drop dead and stop trying.


    Ignoring the "drop dead" part, remember that part of the value of
    asking questions here is getting "what you're trying to do isn't
    useful" type answers. There's room for both kinds.

    /Jorgen

    --
    // Jorgen Grahn <grahn@ Oo o. . .
    \X/ snipabacken.se> O o .
    Jorgen Grahn, Feb 14, 2013
    #14
  15. On Thursday, February 14, 2013 12:38:25 PM UTC-6, Luca Risolia wrote:
    > On 14/02/2013 05:43, Nephi Immortal wrote:
    >
    > > I ask you for your opinion what chained function name look like. I do not need to post class definition since you know what I am talking about.

    >
    > >

    >
    > > Let’s say for example I have 'A' class.

    >
    > >

    >
    > > A a( 1 ), b( 2 ), c( 3 );

    >
    > > int data = a.get_value();

    >
    > > a.set_value( 2 );

    >
    > >

    >
    > > What if I am going to write like this below?

    >
    > >

    >
    > > a.set_value( b.get_value() + c.get_value() );

    >
    > >

    >
    > > They can be to include operator=, operator+, and operator cast. It looks very readable than getter and setter.

    >
    > >

    >
    > > a = b + c;

    >
    > >

    >
    > > What if I choose to use chained function name?

    >
    > >

    >
    > > a.value() = b.value() + c.value();

    >
    > >

    >
    > > Is that readable?

    >
    > >

    >
    > > If I name value1() and value2(), I may not want to place them in the main class. I rather prefer to place them in the nested class.

    >
    > >

    >
    > > a.Inner().value1() = b.Inner().value1() + c.Inner().value2();

    >
    > >

    >
    > > What if I don’t like “Inner()”? It should be removed and operator()() is used.

    >
    > >

    >
    > > a().value1() = b().value1() + c().value2();

    >
    > >

    >
    > > Do chained function name sound good?

    >
    > >

    >
    >
    >
    > "a = b + c" looks good. All the other alternatives are more difficult to
    >
    > read.
    >
    >
    >
    > > Let’s give some ideas.

    >
    > >

    >
    > > int data1, data2, data3;

    >
    > >

    >
    > > data1 = a.Get().Bytes();

    >
    > > data2 = b.Get().Kilobytes();

    >
    > > data3 = c.Get().Megabytes();

    >
    > >

    >
    > > a.Set().Bytes( 1 );

    >
    > > b.Set().Kilobytes( 2 );

    >
    > > c.Set().Megabytes( 3 );

    >
    > >

    >
    > > data1 = a().Bytes();

    >
    > > data2 = b().Kilobytes();

    >
    > > data3 = c().Megabytes();

    >
    > >

    >
    > > a().Bytes() = 1;

    >
    > > b().Kilobytes() = 2;

    >
    > > c().Megabytes() = 3;

    >
    > >

    >
    > > a().Bytes() = b().Kilobytes() + c().Megabytes();

    >
    > >

    >
    > > Please comment if my code looks readable.

    >
    >
    >
    > I think it is not readable. It's not type-safe for sure, which makes
    >
    > your code error-prone. You might loose your spacecraft in the space.
    >
    >
    >
    > I would suggest a more modern and safe approach, for example:
    >
    >
    >
    > #include <iostream>
    >
    >
    >
    > template<int UB, int US>
    >
    > struct Unit { // a unit in the SI/IEEE systems
    >
    > enum { B=UB, s=US }; // bytes and seconds
    >
    > };
    >
    >
    >
    > template<typename Unit> // a magnitude with a unit
    >
    > struct Value {
    >
    > double val; // the magnitude
    >
    > explicit constexpr Value(double d) : val(d) {} // construct a Value
    >
    > from a double
    >
    > // other constructors...
    >
    > Value operator+(const Value& x) {
    >
    > return Value(val + x.val);
    >
    > }
    >
    > };
    >
    >
    >
    > using Byte = Unit<1, 0>; // unit: byte
    >
    > using MemBlock = Value<Byte>; // shortcut
    >
    >
    >
    > constexpr Value<Byte> operator"" _B(long double d) {
    >
    > return Value<Byte> (d);
    >
    > }
    >
    >
    >
    > constexpr Value<Byte> operator"" _kB(long double d) {
    >
    > return Value<Byte> (d * 1024);
    >
    > }
    >
    >
    >
    > constexpr Value<Byte> operator"" _MB(long double d) {
    >
    > return Value<Byte> (d * 1024 * 1024);
    >
    > }
    >
    >
    >
    > constexpr double to_B(const Value<Byte>& b) { // free functions to be simple
    >
    > return b.val;
    >
    > }
    >
    >
    >
    > constexpr double to_kB(const Value<Byte>& b) {
    >
    > return b.val / 1024;
    >
    > }
    >
    >
    >
    > constexpr double to_MB(const Value<Byte>& b) {
    >
    > return b.val / 1024 / 1024;
    >
    > }
    >
    >
    >
    > // Let's add something useful to the example
    >
    > using Second = Unit<0, 1>; // unit: sec.
    >
    > // using Second2 = Unit<0, 2>; // s^2
    >
    > using Time = Value<Second>; // time in seconds by default
    >
    > using TransferRate = Value<Unit<1, -1>>; // bytes/second type
    >
    >
    >
    > constexpr Value<Second> operator"" _s(long double d) {
    >
    > return Value<Second> (d);
    >
    > }
    >
    >
    >
    > constexpr double to_s(const Value<Second>& s) {
    >
    > return s.val;
    >
    > }
    >
    >
    >
    > constexpr TransferRate operator/(const MemBlock& m, const Time& s) {
    >
    > return TransferRate(to_B(m) / to_s(s));
    >
    > }
    >
    >
    >
    > int main() {
    >
    > MemBlock a = 1024.0_B;
    >
    > //MemBlock b = 3.0; // NOT OK! unit needed
    >
    > auto b = 3.0_kB; // OK
    >
    > auto c = a + b;
    >
    > std::cout << to_kB(a) << "+" << to_kB(b)
    >
    > << " = " << to_kB(c) << '\n'; // or define your operator<<()
    >
    >
    >
    > // Another example..
    >
    > TransferRate slow = c / 1.0_s;
    >
    > auto fast = slow + slow;
    >
    > // etc..
    >
    > }


    Your code looks good. Unfortunately, Visual C++ 2012 does not compile!
    I looked at MSDN. It says constexpr and other features are not supported.
    I think it only supports partial C++x11. Is that true?

    If yes, can you please revise your code to remove unsupported features.
    Nephi Immortal, Feb 15, 2013
    #15
  16. Nephi Immortal

    Luca Risolia Guest

    On 15/02/2013 03:56, Nephi Immortal wrote:
    > Your code looks good. Unfortunately, Visual C++ 2012 does not compile!
    > I looked at MSDN. It says constexpr and other features are not supported.
    > I think it only supports partial C++x11. Is that true?
    >
    > If yes, can you please revise your code to remove unsupported features.


    I am sorry, but I don't have VC++2012 at the moment, so I can't answer.
    I used GCC 4.7.2:

    https://ideone.com/PHh3g5
    Luca Risolia, Feb 15, 2013
    #16
  17. Nephi Immortal

    Öö Tiib Guest

    On Thursday, 14 February 2013 18:42:48 UTC+2, Victor Bazarov wrote:
    > On 2/14/2013 10:14 AM, Öö Tiib wrote:
    > > [..]
    > > 'value' (as noun) can not be considered non-property of something whose
    > > 'value' it is. I never provide properties as L-Values for any by-passer
    > > to store references at and change at will. I feel it error-prone.
    > >
    > > I prefer immutable (after construction) properties. I feel it is safer
    > > It can be LOT more efficient if property's value is even set
    > > compile-time. Consider such things about every property.
    > >
    > > If there is certain need to mutate a property during object's life-time
    > > then it deserves command-like operations named by verbs. It is better
    > > to make such operations as safe and complete as possible. Keep invariant
    > > of whole object under its own control.
    > >
    > > 'value' is still hard example since it is fitting verb too. On such cases
    > > I prefer to use some synonymous verb (like 'assess', 'estimate', 'evaluate')
    > > to reduce the possible confusion:
    > >
    > > a.revalue( b.price() + c.net_value() );

    >
    > Uh... Perhaps it's a wrong path we're trying to follow. 'Price' is a
    > verb as well as a noun, 'estimate' is a noun as well as a verb... :)


    It is difficult only because of so lot of verbs and nouns are homonyms
    in English. In Russian for example where commanding verb rarely is
    homonym for some noun it would not be problem at all. It is not
    wrong in English ... just more difficult.

    > There is something to be said about 'set' as well (it's a noun too, I am
    > sure you've heard of 'std::set' :*)), but in combination with another
    > word it is less likely to be confused. I would definitely prefer
    > 'set_value' to 'revalue' (along with 'value' as a "get"-like accessor).
    > But that's just me. Keep in mind that readability is still
    > subjective, let's not try to deceive *ourselves* into thinking that
    > there can be a complete set of readability rules suitable for everybody.


    When I see some code that is easy to read then it is usually master
    involved. So it is art. What rules can achieve is uniform quality that
    is usually readable enough. Worst is inconsistent mix of unfitting and
    contradicting concepts. Your usage of set prefix is great for me if it
    is used consistently for same thing all over the code-base.
    Öö Tiib, Feb 16, 2013
    #17
  18. Nephi Immortal

    Öö Tiib Guest

    On Thursday, 14 February 2013 23:50:08 UTC+2, Jorgen Grahn wrote:
    > On Thu, 2013-02-14, Öö Tiib wrote:
    > > On Thursday, 14 February 2013 16:27:29 UTC+2, Jeff Flinn wrote:

    > ...
    > >> I would avoid the whole approach. I'm assuming the OP's example is just
    > >> that: a paired down example. Without a clearer def of the class in
    > >> question it's difficult to say what approach should be used, indeed are
    > >> these accessor/mutator pairs even needed.

    > >
    > > Try to be more constructive? Your answer feels like Nephi should just
    > > drop dead and stop trying.

    >
    > Ignoring the "drop dead" part, remember that part of the value of
    > asking questions here is getting "what you're trying to do isn't
    > useful" type answers. There's room for both kinds.


    There is. Trying to make some rules how to name classes, variables
    and functions in your code feels like good idea. So I disagreed that
    it does deserve such answer. I trust that it is worth trying. There
    maybe can not be universal naming approach that fits for every
    problem domain but everybody end up using something. It makes
    life easier.
    Öö Tiib, Feb 16, 2013
    #18
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike H
    Replies:
    1
    Views:
    688
    Chris Smith
    Feb 27, 2004
  2. Volker Grabsch

    Multiple "cmp"s chained one after another

    Volker Grabsch, May 14, 2005, in forum: Python
    Replies:
    11
    Views:
    499
    Glauco Silva
    May 16, 2005
  3. Sathyaish

    Chained Comparisons

    Sathyaish, Mar 20, 2006, in forum: Python
    Replies:
    15
    Views:
    511
    Dennis Lee Bieber
    Mar 20, 2006
  4. David S.

    chained attrgetter

    David S., Oct 25, 2006, in forum: Python
    Replies:
    4
    Views:
    310
    David S.
    Oct 26, 2006
  5. Julia
    Replies:
    79
    Views:
    2,469
    James Dow Allen
    Feb 9, 2007
Loading...

Share This Page