Prev: Critique of Robert C. Martin's "Agile Principles, Patterns, and Practices"
Next: "Modern" Software Framework?
From: John Carter on 31 Jul 2007 21:38 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 1 Aug 2007 08:35 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 1 Aug 2007 09:13 "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 1 Aug 2007 11:31 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 1 Aug 2007 13:03 "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
|
Next
|
Last
Pages: 1 2 Prev: Critique of Robert C. Martin's "Agile Principles, Patterns, and Practices" Next: "Modern" Software Framework? |