Archived

This forum has been archived. Please start a new discussion on GitHub.

nonmutating semantics precision needed

The nonmutating method hint is a little bit confusing to me.
It is said (p.83):

interface Clock {
nonmutating TimeOfDay getTime();
void setTime(TimeOfDay time);
};
The nonmutating keyword indicates that the getTime operation does not change the state of its object.

I have hard time understanding what an "object state" is given i am supposed to work only against interfaces that can be mapped to any implementation on the server side.

You also explain that the nonmutating hint means that (given a set of parameters ?), the method can be called more than once before returning without harm: I understand that this is the interface designer choice to make some methods nonmutating or not, and that this choice is often made with an implementation in mind.

For example, it effectively does not harm to call getTime() many times, even if the Clock implementation on the server is a real-time Clock (and not just an object with a TimeOfDay property).

The same reasoning may apply to interfaces that do not store any state by themselves, for example a proxy to make predefined requests to a database, even if the result may be different between the different call attempts.

Is this point of view compatible with your definition of the nonmutating keyword?
--
Christophe

Comments

  • marc
    marc Florida
    Since slice is not only an interface specification language, but also a persistent state description language, it is important to tell persistence services such as Freeze which operations change state and which do not. If a nonmutating operation is called, Freeze does not need to save the state of an object.

    For an example of nonmutating operations for the purpose of automatic object persistence, have a look at the example in demo/Freeze/library.

    nonmutating also has side effects for certain language mappings, such as making a method const in the case of C++.

    nonmutating implies idempotent. Idempotent means that it's safe to call a method more than once with the same parameters without any side effects. All nonmutating operations are idempotent, but not all idempotent operations are nonmutating. For example, an operation setAbsoluteTimeOfDay() would be idempotent, but it would not be nonmutating. An operation addToTimeOfDay() would neither be nonmutating nor idempotent.

    Declaring operations as idempotent is important because then the Ice core can use more aggressive retry strategies in the case of communications failure. Without an operation being marked as idempotent, Ice has to guarantee "at-most-once", meaning that an operation is either called exactly once, or an error is raised with the caller. If it is marked as idempotent, the Ice core is free to disregard this "at-most-once" guarantee.
  • Thanks for your quick answer.

    I better understand the implications and the benefits of the nonmutating and idempotent keywords now, but let me be more specifics:

    I am in the process of writing some best practices, or guidelines, for developers and architects that where accustomed to work with CORBA.

    Among the subjects i want to clarify is the good use of the nonmutating keyword, and i was w(a)ondering if:

    Is it recommended / permissible / forbidden to use nonmutating methods for objects that do not hold state by themselves and whose return value is always the result of a "best effort", a situation which i guess is also idempotent (in the spirit of my db request example).

    Because from my point of view it is safe to call such method more than once, a nonmutating method is permitted.
    The expected added-value being that the retry process is done by the Ice runtime, and not by a developer.

    But, even in this situation, there is some internal limitations, or use cases (like using Freeze) that i am not aware of, so your advice is valuable.
    --
    Christophe
  • Originally posted by annekat
    Is it recommended / permissible / forbidden to use nonmutating methods for objects that do not hold state by themselves and whose return value is always the result of a "best effort", a situation which i guess is also idempotent (in the spirit of my db request example).

    I would make everything idempotent or nonmutating that can safely be restarted in the face of partial failure. Whether this is the case or not, only you as the application developer can decide, because only you know what the implementation of your operations is doing.

    So, if reissuing the database request does no harm, then you might as well mark the operation as nonmutating. In essence, nonmutating captures the idea of (logical) const-correctness -- even though the physical state may have changed somewhere, if that state change is semantically invisible to the clients, the operation is conceptually nonmutating (even if a reissued request may return different data).

    Using idempotent and nonmutating keywords has the benefit of giving you better error recovery and, in addition, for C++, you get slightly better type safety because the corresponding member functions on the skeleton become const member functions.

    Cheers,

    Michi.
  • Merci

    Thanks for all your kind answers and clarifications.