This piqued my curiosity. What do you mean, you "use these modules through system()?" Do you just call system("perl MyModlue.pm")? Are you quite sure this "module" is actually a module, in the sense that in defines a handful of subroutines or perhaps an object class, either way a bunch of code that doesn't do much until you tell it to? Or is it really a full fledged script that you actually run, maybe as a part of a larger system or maybe not, but a script nontheless?
When I think module, I think abstraction layer. For example, an example of modules that you could write for some project are:
There happens a bunch of other things "under the hood", but in essence this way of working allows my code to kinda look like this:
This is very much a simplification, but what's relevant here is that the main code is easy to read. From top to bottom, it tells Perl to get the hostnames, connect to them, wrap an IO abstraction layer around those connections, and enter the main loop. Inside the main loop, create an input handler, get a chucnk of input from the IO wrapper, and feed that input to the handler. When the IO wrapper says it has collected a complete set of input chunks, tell the handler to do its work and hand the result back to the IO wrapper. Then read the next chunk of input until there's nothing more to read.
The (imaginary) fact that InputHandler.pm is almost 1000 lines of code, IoSelectWrapper.pm is just over 400 lines, SocketFactory.pm about 100, and More::Stuff is actually 6 different files totalling to around 6000 lines, is completely invisible from the main code. The main code is short, simple, and abstract. All the gory details of creating sockets, connecting to other servers, maintaining those connections, reading data, parsing data, processing that data, and logging the act of processing, are neatly hiddden in their own relevant modules.
Note that none of these modules can run stand-alone. They're all part of a bigger system. IoSelectWrapper, for example, wouldn't have anything to read from without More::Stuff kindly opening connections for it, and InputHandler can't do a thing until IoSelectWrapper begins spitting out data. Also note that none of these modules do a thing until the main code tells them to. IoSelectWrapper just sits around, staring at its nails, only to occasionally read from a few sockets once every iteration. InputHandler is standing in the corner, soaking up everything it sees until its told to process all of that, and while it's processing, IoSelectWrapper can't even get a cup of coffee because this program doesn't use threads or call fork, so everybody in the room waits until InputHandler comes back with its results.
Most of these modules use other modules in turn. For example, SocketFactory will use IO::Socket::INET at the least, IoSelectWrapper surely uses IO::Select and what-else-you've-got. It's likely that they're both built using Moose or Moo or a similar framework.
To come back to my point, when I think module, I think long wall of code, doing all sorts of useful things for me, such that I don't have to bother how it does it. I think subroutines or methods that I will pump data into and that will throw something back at me, and possibly I think of import lists or tags, if the module is written to export stuff. Which my modules are hardly ever — I'm an OO junkie.
I think all that when I think module. I definitely don't think system(...). So I'm wondering, are your "modules" modules? Or are they stand-alone scripts that nevertheless could be part of a bigger system?