Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

a State machine with Roles - possible?

by mascip (Pilgrim)
on May 29, 2013 at 13:13 UTC ( [id://1035838]=perlquestion: print w/replies, xml ) Need Help??

mascip has asked for the wisdom of the Perl Monks concerning the following question:

In this presentation of design patterns in Ruby, on slide 140, Neal Ford uses Mixins to implement a simple State machine: a door which is opened or closed.

What we have closest from Mixins is Roles. So, we can probably do the same thing with Roles. To apply a Role at runtime we have Moose::Util::apply_all_roles() or ensure_all_roles(). But i didn't find how to un-apply a Role.
Is it possible to un-apply a Role?

If yes, then we can implement a State Machine with Roles. It's also possible with Class::StateMachine::Declarative. The latter is probably better for small state machines. I don't know if a Role-based state machine would have any advantages over it for more complex cases.

As i'm not planning to use any of these two in the near future, this is more of a theoretical question. Me, procrastinating by learning more and more stuff that i don't use? Maybe ;-)

EDIT: Later in this thread, a solution to unapply a Role

Replies are listed 'Best First'.
Re: a State machine with Roles - possible?
by salva (Canon) on May 29, 2013 at 13:58 UTC
    On slide 135, it says...
    Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.

    That's exactly what Class::StateMachine does: it re-blesses the objects effectively attaching a different event dispatch table when the state changes. There is no need to use mixins when you can do the real thing!

    The only advantage that mixins could bring to the table is having objects with multidimensional states. But I don't thing this is something practical which anybody would like to use for anything serious.

    BTW, Class::StateMachine::Declarative is been used to model state machines as complex as QVD::HKD::VMHandler::LXC.

      Very clear explanation, cheers! :-)

      More discussion as an answer to LanX, below

Re: a State machine with Roles - possible?
by LanX (Saint) on May 29, 2013 at 13:42 UTC
    Just as a side note.

    Can't tell if it's cleanly done with mixins in Moose but within an inheritance model these state changes should be simply done by manipulating @ISA such that you inherit from another class representing your state.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

Re: a State machine with Roles - possible? (class or instance)
by LanX (Saint) on May 29, 2013 at 15:25 UTC
    These slides are confusing!

    Initially I read the line The object will appear to change its class and had the same idea like salva to simply re-bless an object into a new class.

    But the shown mixin code seems to operate on classes not instances (just like roles in Moose do) ?!?

    Could you please elaborate what you're exactly intending to do?

    UPDATE

    seems like I found the answer on my own:

    Similarly, Object.extend(module, ..) adds the instance methods from each module given as a parameter. However, extend adds the methods to one instance, not to all instances.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      It seems Ruby mixology adds support for per-object mixins.
        Yep, but I think it's a core feature.

        edit: see extend

        Cheers Rolf

        ( addicted to the Perl Programming Language)

      Seems Moose allows you to attach roles to instances, not just classes, with Moose::Util::apply_all_roles($applicant, @roles) by creating a new anonymous class with the object's previous class as superclass and with the roles applied, and then reblessing the object into that class. Not sure the other role implementations have easily accessible methods to do this.


      UPDATE: using Moo::Role or Role::Tiny this seems to work bless $object, Moo::Role->create_class_with_roles(blessed $object, @roles); (replace Moo::Rule with Rule::Tiny for less Moo-ness, and import blessed from Scalar::Util)
        Well yesterday I meditated about ways to implement this in Perl...

        While I don't know the Moose guts, I remember that Moose was said to stay compatible to classical OO, mostly just adding syntactic sugar. ²

        So I suppose that the normal search-path isn't manipulated in Moose.

        This led me to 2 possibilities to implement this (rather JS-ish) requirement.

        > by creating a new anonymous class with the object's previous class as superclass and with the roles applied,

        Thats the first approach I thought about. But I'm worried about side effects. How transparent is this new class in the middle, does the instance still officially belong to the superclass?

        FWIW my approach to implement the OP's state machine would certainly be to openly create sub-classes for each state with a common superclass defining the interface.

        Like this state-changes could simply be realized with reblessings.

        Different roles could still be applied to these "state"-classes, can't see any need to avoid inheritance here.

        The other approach to have individual methods per instance could defining an attribute hash instance_methods which holds names => sub {} for each instance-method.

        However calling this indiviual methods would imply the need to inherit equally named interface methods in the class to delegate the call.¹

        Alternative an AUTOLOAD mechanism comes into mind, but these methods would have the lowest priority in the search path then.

        BUT I can't see any need to implement a state machine this way.

        IMHO the euphoria for mixins in Ruby was taken a bit to far.

        Cheers Rolf

        ( addicted to the Perl Programming Language)

        UPDATE

        ¹) such that  $obj->my_meth() does something like $self->{instance_methods}{my_meth}->(@_).

        ²) plz correct me if I'm wrong!

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1035838]
Approved by marto
Front-paged by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others musing on the Monastery: (2)
As of 2024-03-19 04:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found