Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Re: Modules that reference each other

by mstone (Deacon)
on Sep 29, 2004 at 18:09 UTC ( [id://395085]=note: print w/replies, xml ) Need Help??


in reply to Modules that reference each other

The basic solution is to put all the circular code into the same module.

You might be able to do that simply by moving everything into one of your existing modules, or you might need to create a whole new module. From a design perspective, it's usually best to start by trying to build a completely new module. That tends to highlight the problem that created the circular dependency in the first case.

Functions are easy to move if they don't refer to anything outside themselves. This function:

sub easy_to_move { my @params = @_; $result = [some simple manipulation of @params] return ($result); }

can be picked up and moved anywhere without changing a thing. It isn't aware of anything except its parameter list, so it doesn't care where it lives. Functions that call other functions can be slightly harder to move, but not much.

The thing that makes functions hard to move is a dependency on some kind of data. This function:

sub hard_to_move { my @params = @_; my $anchor = $STATIC_VARIABLE; $result = [something that involves $anchor]; return ($result); }

is hard to move because it's handcuffed to a specific piece of data within the module. Moving the function means finding a way to move the data as well. Modules make it easy to share data among several functions, so the odds are fairly good you'll find some kind of data anchor holding your code in a specific place. Cirular dependency itself is often a sign that your data hasn't been distributed among the modules properly.

That happens. Programming is research, and at every stage you make enough assumptions to carry you to the next stage. Sometimes, along the way, you find subtle problems in your assumptions. That doesn't make you a bad programmer, it just means you're working on something new. The only times you don't run into trouble like that is when you're working on a toy problem that doesn't present any real complexity, or when you're working on something that's been done so many times before that there are no surprises left.

To manage the dependencies, you have to manage your data. To manage your data, you give up the convenience of having everything right there at your fingertips, and pass the data as a parameter.

If you only have to turn one or two values into parameters to make the function portable, just go ahead and pass the values directly. If you find your parameter list getting ridiculously long, create a data structure and pass that. If you do end up creating a data structure, look at the possibility of making that structure a parameter for the entire module, not just for the function you want to move.

Many circular dependencies can be solved by paritioning the code into 'data storage' and 'data manipulation' modules. The basic rules of such modules are that 'storage' modules do only that. They don't contain any manipulation code that isn't absolutely trivial. 'Manipulation' modules, OTOH, don't contain any data of their own. They just manipulate whatever the storage module gives them.

Most code contains a mix of those two kinds of behavior, and usually that's no problem. When you run into circular dependencies, though, it's time to get very strict about your division of responsibilities until the dependency problems go away.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://395085]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (2)
As of 2024-04-19 18:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found