"Jamis Buck" <jgb3 / email.byu.edu> schrieb im Newsbeitrag
news:412893BB.1050506 / email.byu.edu...
> Robert Klemme wrote:
>
> > Some remarks: #freeze might do what you want if you want to prevent any
> > change after a certain point in time.
>
> True, except I don't want to prevent *all* changes. (I know the example
> I used gave that impression, but it wasn't a complete example). I only
> want to prevent certain methods from doing useful work after a certain
> point in time.

Yeah, I guessed so.  Just wanted to make sure freeze didn't go unnoticed.

> > I would not use NotImplementedException because that generates the false
> > impression that an undefined method was invoked while really it was a
state
> > violation (in Java you'd use IllegalStateException for this).
>
> True. It was just the example. In my code I've got a custom
> "DisallowedOperationException" that I throw.

Ah, I see.

> > While using extend might work it's not easy to reverse (if you want to
reset
> > an instance's state later for example).
>
> Another good point. However, in my code, it is not intended to be
> reversable. Once an object has been fixated, it cannot be "unfixated".
> You're right, though--if it had needed to be reversible, the
> module-based approach might not have been as feasible (unless I had two
> modules, one for each state of the object...which could get ugly).

And I wouldn't know how to make this work: AFAIK there is no unextend and
once you've extended your instance by all modules, further extension doesn't
change anything:

>> module ModA; def foo() "foo" end; end
=> nil
>> module ModB; def foo() "bar" end; end
=> nil
>> class Foo; def foo() "xxx" end ; end
=> nil
>> f=Foo.new
=> #<Foo:0x10171fc8>
>> f.foo
=> "xxx"
>> f.extend ModA
=> #<Foo:0x10171fc8>
>> f.foo
=> "foo"
>> f.extend ModB
=> #<Foo:0x10171fc8>
>> f.foo
=> "bar"
>> f.extend ModA
=> #<Foo:0x10171fc8>
>> f.foo
=> "bar"

> > So I'd rather use either strategy pattern (or state pattern, they are
quite
> > similar) or model states with constants (less typing than those patterns
but
> > better documentation IMHO because each method states clearly what
> > precondition it has; and might be a bit more runtime overhead).
>
> I knew someone would have some great suggestions! :) Thanks, Robert.

You're welcome.

> Either of those patterns would have worked as well. The state-based
> approach (which you demonstrated) is especially compelling. Although, I
> think I like the module-based approach because it eliminates the need
> for (1) extra state information (like the @state variable) and (2)
> condition testing (like the 'pre' method), which could become expensive.

It shares (2) with strategy/state pattern but with the added advantage of
saving a method call (the delegation).  In fact, the longer I think about it
the more I like the module approach because it is very similar to the state
pattern but saves the overhead (you named it) - if only there would be a way
to unextend a module.  That's really the biggest showstopper for using
mixins to implement state pattern.  Darn...

> I'm all in favor of preconditions, though... your suggestion is one I'll
> certainly be adding to my toolbox. :)

I'm glad that I could share some useful thoughts.

> "I use octal until I get to 8, and then I switch to decimal."

How do you get to "8" in octal?  Is there a new variant "octal plus" that
has other digits than 0,1,2,3,4,5,6,7? :-)

Kind regards

    robert