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

Hi! I'm having a hard time refactoring some modules which have cyclical dependencies. Example:
package Aa; use Bb; my $object = Bb->new();
and
package Bb; use Aa; my $object = Aa->new();
Obviously, bad arhitecture, but a lot of other things depend on these, so I wasn't sure how can I solve these things. I know this is not entirely related to Perl, it has more to do with programming theory, but I thought Perl has some specific things regarding this, like how could I use some design pattern, if there is one for these situations. There are some other kinds of cyclical dependencies too, like
package Aa; use Bb; my $result = Bb::some_function_which_does_not_create_object();
and
package Bb; use Aa; my $object = Aa::some_function_which_does_not_create_object();
These can be broken sometimes by taking out one modules functionality and putting it into another module (class) and then each of the 2 modules can use this new one, breaking the cycle, but this solution is not working all the times either. Could any one help me towards this? Thanks in advance, faceless.

Replies are listed 'Best First'.
Re: Trying to break cyclical dependencies in Perl modules
by Utilitarian (Vicar) on Sep 07, 2010 at 10:31 UTC
    package Aa; use Bb::Util;
    I would take the related but non-essential methods out of the core Bb package.

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: Trying to break cyclical dependencies in Perl modules
by JavaFan (Canon) on Sep 07, 2010 at 11:25 UTC
    In your first example, an easy way of breaking the cycle is to put the sub new before the use statement (in both files). The problem here isn't the cycle by itself, it's that both modules, at compile-time need code defined by the other. Code that hasn't been compiled yet. Moving the $object = Bb->new(); inside a method that only gets called at runtime should solve this problem as well.
Re: Trying to break cyclical dependencies in Perl modules
by bart (Canon) on Sep 07, 2010 at 18:07 UTC
    If Aa requires Bb and Bb requires Aa, then both must always be loaded together, so there is no reason to use separate files for both. So: just put them in a common source file. That way you're transferring the execution time of code from the other module, that each module wants to run at their own compile time (as JavaFan pointed out, and which is impossible), to straightforward sequential execution. Problem fixed.
      It seems that merging the two source files was the solution. Thank you very much for your help, and thanks for the others too for the answers :)
Re: Trying to break cyclical dependencies in Perl modules
by tospo (Hermit) on Sep 07, 2010 at 13:13 UTC
    To me this looks like Aa and Bb should actually inherit from a common Ab(or whatever)::Base class.
Re: Trying to break cyclical dependencies in Perl modules
by ikegami (Patriarch) on Sep 07, 2010 at 15:53 UTC
    Cyclical dependencies don't matter except in some circumstances where symbols are exported. Since you're dealing with objects (and that's the normal scenario for such dependencies), you don't have to do anything.