|Think about Loose Coupling|
This is one part where I think it is essential to take a step back and forget everything you know about any programming languages you have learned.
The problem here is that both module and function are highly overloaded concepts. Sometimes modules are building blocks as in other engineering disciplines, sometimes they are an abstraction mechanism, sometimes they are a particular way in your programming language to encapsulate functionality, ... Similarly functions could be procedures, methods, subroutines, lambda expressions, or mathematical functions (which could be mappings or relations), or what have you. Let's forget all about that, too.
Actually, let's give a new name for the concept.
Let gob have the following meaning: Any particular functionally sensible piece of program text that has a well-defined interface through which it can be used and with which it can be connected to other gobs.
Given this meaning, a computer program is a gob: it accepts some input and produces some output. (If you want, the input and output can be partially or completely the global state of the machine.) A computer program can be connected to other gobs through its input and output.
A class in object-oriented programming is a gob: the well-defined interface is the public methods, and these are used when connecting the class to other classes (gobs).
A module in, say, Perl, is a gob: whether it is object-oriented, functional, or a collection of procedures, it has some interface through which it can be used. The interface can again be used to connect it to other gobs.
A function/routine/subroutine/procedure is a gob: the interface to a function is the parameters it accepts (the input) and the return values (the output). (If you want, it may also partially affect the (global) state of the machine, i.e. work through side-effects.) The interface can, again, be used to connect this gob to other gobs.
This is what I mean. At a very high level, all current programming paradigms let you create gobs and pass gobs as parameters to other gobs. How gobs are implemented in your particular programming language is not relevant; the concept is! Gob is the quintessential Lego block of programming, if you want.
Suppose you have that small statistical analysis framework. One gob abstracts the control: it takes in data in some form, processes the data chunk by chunk by giving it to another gob (supplied by user), which returns a value, and the value is given to a third gob (supplied by user) along with the ID number of the data chunk. The user provides such a pair of gobs that they work well together (the latter understands the output format of the former), and the framework is completely agnostic to what kind of data these two gobs pass around; it just connects the gobs together and provides them with small pieces of data.
How you might implement this could be with three classes: one for control, another for data analysis, and a third for data collection or plotting.
Or you could implement the control as a function that takes two closures as parameters.
Or you could implement the control as a function that takes two objects as parameters.
In a word, this is what I mean with gob.
(As an aside, gob is an actual word.)
In reply to Re^4: I dislike object-oriented programming in general