"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