Building simplicidade.org: notes, projects, and occasional rants

Sane policy for cyclic module dependencies

In medium-to-large Perl projects (case in point has 164 .pm files, far from over), cyclic module dependencies can become a issue.

Usually I use a lot of Module::Pluggable stuff, coupled with registry-style approaches. So each module is dynamically loaded based on his namespace using Module::Pluggable and registers itself into the core application.

The problem usually crops up when some registry class also requires a module that uses its services. For example, a registry module that uses a DBIx::Class schema, and some of the Tables use that same registry.

If your Registry class uses the your Schema, to make sure it is loaded, then the definition of the registry method will not be available when the Table classes are loading.

There are several possible solutions to this.

First, you could simple split your Registry class into a simple Registry and Registry::DB methods. This way, the Registry will not have the Schema dependency and all will just work. I don't like this much because the split is not natural in some situations.

Another approach is to limit the uses on each module to the minimal number of classes you need to load the module. In this case, the Registry doesn't need to use the Schema class if he doesn't require it during the compilation phase. If you only use the Schema in some methods, you only need to make sure it is loaded at the time of the method call. This can be scary if you look at the code and see a module being used without the proper use first.

A third approach is to do the least amount of stuff during compile time and use the INIT or CHECK blocks to do the proper initialization of your modules. This would be my favorite but I'm uncertain of the problems with mod_perl. (on a side note, be sure to check the proper documentation to learn about these Perl blocks: the begincheck program in there is very enlightening).

In the end, I usually use a combination of the first two. I do plan to see what are the caveats with INIT and CHECK in mod_perl, given that it would be a much better approach.