Boost logo

Boost :

Subject: Re: [boost] [review][constrained_value] Review of ConstrainedValueLibrary begins today
From: Stjepan Rajko (stjepan.rajko_at_[hidden])
Date: 2008-12-08 12:01:08


On Mon, Dec 8, 2008 at 9:35 AM, Robert Kawulak <robert.kawulak_at_[hidden]> wrote:
>> From: Stjepan Rajko
>
>> I am inclined to think that the implementation you have now (minus the
>> asserts and the nomenclature) covers all of the uses fairly well.
>> Existence of in-between use cases (conditionally monitored values,
>> e.g., log whenever the temperature is over 35 degrees Celsius) leads
>> me to believe that neither of {monitored value, conditional value}
>> should be implemented in terms of the other. I think they should be
>> implemented under a common abstraction, and I think your
>> implementation implements that abstraction (again, minus the asserts
>> and the nomenclature).
>
> I think the current implementation is not the most suitable one for monitored
> values. The asignment operator is:
>
> if( constraint()(v) )
> _value() = v;
> else
> error_handler()(_value(), v, _constraint());
>
> So calling the monitor (error_handler) excludes assignment of the value, unless
> the monitor performs the assignment by itself. This is a bit clumsy -- e.g.,
> having the case with logging the temperature if it exceeds a treshold, monitor
> would not only have to log, but also to assign the value.
>
> I see implementation of monitored values' assignment a bit different:
>
> if( _monitor(_value, new_value) ) // monitor decides whether the value
> should be assigned
> _value = new_value; // but does not perform the assignment by
> itself
>
> Then, conditionally-monitored values extend this by defining the following
> monitor callback:
>
> if( _condition(new_value) ) // no need to invoke the monitor
> return true;
> else // invoke the monitor
> return _monitor(old_value, new_value, _condition);
>
> And finally, constrained value would be a conditionally-monitored value, where
> the condition is the constraint and the inner monitor callback is the error
> policy.
>

Then you have a different mechanism for monitored vs. conditionally
monitored values. Instead, you could have a wrapper for the policy
that does the assignment for you.

purely_monitored_value<T, action> expands to:
what_is_now_called_constrained<T, always_false, always_assign<action> >

>> For now, I would be plenty happy if you just took out the asserts, or
>> made them optional (with defaulting to asserts, if you wish). That
>> way I can at least start experimenting with your library in a
>> monitored_value context, and let you know how it goes (I have use
>> cases for this).
>
> By saying about making the invariant asserts optional you mean something like
> wrapping them in a conditional compilation macro (like
> BOOST_CONSTRAINED_VALUE_NO_INVARIANT_ASSERTS) to be able to turn them off
> globally?
>

That would be fine.

> I still can't convince myself to the idea of separating invariant from the test.
> IMO guarantee of the invariant is a strong point of the library. Giving up the
> guarantee not only may make the library more complicated for the users, but it
> may also lower the value of the library as a debugging device (since there will
> be less checks for coherence of the given set of policies, more opportunities to
> make a bug).
>

You do *not* give up the invariant. You are just saying that the test
and the invariant are not the same thing. You still always guarantee
the invariant. Not only that, but allowing wiggle room between the
test and invariant allows you to guarantee invariants where before you
couldn't.

Furthermore, I think that the case where the test and invariant are
the same thing is very important, and should take a prominent place in
the library documentation. For example: take what you have in the
documentation right now that depends on test <==> invariant, and call
it "Perfectly Constrained Values" or "Verifiably/testably Constrained
Values" or something. Then briefly discuss the test ==> invariant
case as "look, you can do this too, just understand that the test
doesn't test for the invariant exactly".

If you think about it, you are already separating the test from the
invariant in your advanced examples. Think about the object that uses
the library to keep track of it's min/max. The test checks for
whether you have crossed the previous min/max. Sure, you could say
the invariant is the same: "the object is between the min and max
present in the constraint object". But really, what kind of guarantee
is this? If I need to look at the constraint to figure out what I'm
being guaranteed, I might as well look at the value itself and see
where it stands. I would consider this as "no invariant". There, you
already have docs for this case :-)

Best,

Stjepan


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk