There can be a lot of reasons to chose the one or the other. The main drivers are:
- Reuse and maintainabilitySeparation of concerns: Seeking forWhen the function gets the data itself, it constraints the functionitself to one single way of getting the data (e.g. calling another function) and at onejust in time (nowdata is from now). This prevents to reuse the function with different sources, of working with possible futuredoes not allow alternate states of data (simulations). Having the caller chose the sources and assemble the pieces calling the functions with arguments, also facilitates maintainability (e.g. simulations), and makes maintenance difficult if access to the sources would evolve. Depending on how complex it is to get the data, it might need digging into details at a lower level of abstraction and doing more than one thing (clean code).
- Complexity and constraintsConstraints: Seeking forWhen the functions seeks data by itself, it might require lengthy computation at the wrong moment, or overhead such as requiring the source to cache the data (not always possible) or might need digging into details at a lower level of abstraction and doing more than one thing (clean code). But "might" means that there are also cases where this is irrelevant.
The plug&play approach, i.e. letting the context chose the source and assemble the details by calling functions with parameters (doesn't need to be the data: can also be the injection of the function to be used to find the data) is quite robust in this regard. But if none of theses matters are relevant in you case, you have a real choice.