From: John Carter on
In Bertrand Meyers book "Object oriented Software Construction" 2nd Ed he
says section $11.8....(Discussing class invariants)

"The precondition of a routine may involve the _initial state_ and the
arguments."

(Emphasis mine)

I would argue that is a mistake. Since if the precondition involves the
state of the object, it implies the calling routine must know the state of
the object.

This tends to be a violation of the "tell, don't ask" formulation of the
Law of Demeter.

For example...
// In the client code...
if( a.isSomePredicate())
a.doThis();
else
a.doThat();
end
// In the object code...

void A::dothis()
{
assert_precondition( isSomePredicate());
.....
}


instead of the better pattern of...

// In client code...
a.doTheRightThing();

// In the object code...

class A {
private:
void doThis();
void doThat();
bool isSomePredicate();

public:
void dotheRightThing() {
if( a.isSomePredicate())
a.doThis();
else
a.doThat();
}

};

Consider a typical example...

while( stream.notEmpty?()) {
value = stream.getNext();
// do stuff...
}

This tends is messy and tends to be prone to errors arise out of the
predicate changing value between the notEmpty? call and the getNext()

Here we require getNext only to be invoked if notEmpty? is true. ie. The
precondition involves the state..

Consider the fairly typical libc like API....

result = getNext();
while( result != EOF) {
// do stuff

result = getNext();
}

And even better pattern is the Rubyish yield based iterators...

stream.each { |value|
# Do stuff with value
}

Here the block
{ |value|
# Do stuff with value
}

only ever gets invoked if notEmpty? is true

Question 1 to the group:

Can you think of a case where the precondition _must_ involve the state?

Question 2 to the group:

Can you think of a case where the code is improved by allowing
the precondition to depend on the state?

Thank you,
From: Daniel T. on
John Carter <john.cartNeOr(a)StPaAiMt.co.nz> wrote:

> In Bertrand Meyers book "Object oriented Software Construction" 2nd Ed he
> says section $11.8....(Discussing class invariants)
>
> "The precondition of a routine may involve the _initial state_ and the
> arguments."
>
> (Emphasis mine)
>
> I would argue that is a mistake. Since if the precondition involves the
> state of the object, it implies the calling routine must know the state of
> the object.
>
> This tends to be a violation of the "tell, don't ask" formulation of the
> Law of Demeter.
>
> Question 1 to the group:
>
> Can you think of a case where the precondition _must_ involve the state?

No. I agree with your sentiments whole heartily. You never seem to
explain *why* pre-conditions should not reference the objects initial
state except to say that it breaks "tell, don't ask" though. What is so
special about "tell, don't ask"?

There are two basic reasons. (1) in a multi-threaded environment, what
is true now, won't necessarily be true later. Mr. Meyers expects to fix
that by changing the nature of preconditions so that they block until
true, but that isn't always what is wanted. (2) Such preconditions often
are a repeat of the invariant of the class. Moving an invariant to a
precondition is tantamount to foisting the class responsibility to all
of its clients. This sort of distributed responsibility forces much code
duplication.
From: S Perryman on
"Daniel T." <daniel_t(a)earthlink.net> wrote in message
news:daniel_t-201055.08351101082007(a)news.earthlink.net...

> John Carter <john.cartNeOr(a)StPaAiMt.co.nz> wrote:

>> Can you think of a case where the precondition _must_ involve the state?

> No. I agree with your sentiments whole heartily. You never seem to
> explain *why* pre-conditions should not reference the objects initial
> state except to say that it breaks "tell, don't ask" though. What is so
> special about "tell, don't ask"?

> There are two basic reasons. (1) in a multi-threaded environment, what
> is true now, won't necessarily be true later. Mr. Meyers expects to fix
> that by changing the nature of preconditions so that they block until
> true, but that isn't always what is wanted.

This is a fundamental mis-representation of what Bertrand Meyer has
written on concurrency (the SCOOP concept specifically) .

The use of pre-conditions as a resource access control mechanism
in concurrent execution envs is decided on a per-type basis.
It is not all or nothing.


> (2) Such preconditions often are a repeat of the invariant of the class.

I have never seen a pre-condition that is a 'repeat' of an invariant.
Feel free to give an example.

OTOH, many basic ADTs (dates, numeric ranges etc) often have pre/invariant
conditions that can be defined in terms of a *common* (parametric)
condition.
Which by definition is not repetition (unless all parametric terms are the
same) ,
merely good factoring.


Regards,
Steven Perryman


From: Daniel T. on
In article <f8q0tl$q07$1(a)aioe.org>, "S Perryman" <a(a)a.net> wrote:

> "Daniel T." <daniel_t(a)earthlink.net> wrote in message
> news:daniel_t-201055.08351101082007(a)news.earthlink.net...
>
> > John Carter <john.cartNeOr(a)StPaAiMt.co.nz> wrote:
>
> >> Can you think of a case where the precondition _must_ involve the state?
>
> > No. I agree with your sentiments whole heartily. You never seem to
> > explain *why* pre-conditions should not reference the objects initial
> > state except to say that it breaks "tell, don't ask" though. What is so
> > special about "tell, don't ask"?
>
> > There are two basic reasons. (1) in a multi-threaded environment, what
> > is true now, won't necessarily be true later. Mr. Meyer expects to fix
> > that by changing the nature of preconditions so that they block until
> > true, but that isn't always what is wanted.
>
> This is a fundamental mis-representation of what Bertrand Meyer has
> written on concurrency (the SCOOP concept specifically) .
>
> The use of pre-conditions as a resource access control mechanism
> in concurrent execution envs is decided on a per-type basis.
> It is not all or nothing.

This may be true. All I have to go on is OOSC2, I have not kept up with
the latest in Eiffel and SCOOP. In his book, Meyer clearly says (in the
Separate call semantics block on page 996) "Before it can start
executing the routine's body, a separate call must wait until every...
separate precondition clause is satisfied."

> > (2) Such preconditions often are a repeat of the invariant of the class.
>
> I have never seen a pre-condition that is a 'repeat' of an invariant.
> Feel free to give an example.

class RANGE
feature
low : INTEGER
high : INTEGER

setLow( value : INTEGER )
require value < high
ensure low = value
high = old high
end

invariant
low < high
end

My Eiffel is a bit rusty, but notice how "value < high" is basically the
same as "low < high" because "setLow" assures the equivalence between
"low" and "value"
From: S Perryman on
"Daniel T." <daniel_t(a)earthlink.net> wrote in message
news:daniel_t-F4F6A4.11311801082007(a)news.west.earthlink.net...

> In article <f8q0tl$q07$1(a)aioe.org>, "S Perryman" <a(a)a.net> wrote:

JC>Can you think of a case where the precondition _must_ involve the state?

DT> No. I agree with your sentiments whole heartily. You never seem to
DT> explain *why* pre-conditions should not reference the objects initial
DT> state except to say that it breaks "tell, don't ask" though. What is so
DT> special about "tell, don't ask"?

DT> There are two basic reasons. (1) in a multi-threaded environment, what
DT> is true now, won't necessarily be true later. Mr. Meyer expects to fix
DT> that by changing the nature of preconditions so that they block until
DT> true, but that isn't always what is wanted.

>> This is a fundamental mis-representation of what Bertrand Meyer has
>> written on concurrency (the SCOOP concept specifically) .

>> The use of pre-conditions as a resource access control mechanism
>> in concurrent execution envs is decided on a per-type basis.
>> It is not all or nothing.

> This may be true. All I have to go on is OOSC2, I have not kept up with
> the latest in Eiffel and SCOOP. In his book, Meyer clearly says (in the
> Separate call semantics block on page 996) "Before it can start
> executing the routine's body, a separate call must wait until every...
> separate precondition clause is satisfied."

Correct.
What I cannot recall offhand is whether the "separate" designation is
type-wide (all ops) , or type + operation-specific (the latter being the
most flexible) .


DT> (2) Such preconditions often are a repeat of the invariant of the class.

>> I have never seen a pre-condition that is a 'repeat' of an invariant.
>> Feel free to give an example.

> class RANGE
> feature
> low : INTEGER
> high : INTEGER

> setLow( value : INTEGER )
> require value < high
> ensure low = value
> high = old high
> end

> invariant
> low < high
> end

> My Eiffel is a bit rusty, but notice how "value < high" is basically the
> same as "low < high" because "setLow" assures the equivalence between
> "low" and "value"

(value < SELF.high) is not the same condition as (SELF.low < SELF.high) .

Both use a common operation ( < ) , and parameter (SELF.high) .
But neither of the above makes one condition "repeat" the other (you need
value = SELF.low in order to achieve that) .


Regards,
Steven Perryman