How to decide between module_exists and function_exists? I'm familiar with using module_exists in a module, and using it in situations like:


Enable some extra functionality in a module, provided some other module is available in the site also. The Reservations: Email module contains an example (actually there are plenty of examples of this), as shown in its module source: to use tokens (in the eMail body) requires that the Token module is enabled.
Implement module dependencies in a theme, as shown in the answer to "How to implement module dependencies in a theme and package modules with a theme?".


However, there is also function_exists, such as shown in the answer to "Is it possible to declare a Javascript library dependency at Hook.info?".

I have the impression that using function_exists is a more robust (safe) approach as compared to module_exists. Especially if you want to be sure that some function (added in a newer version of a module) is available, whereas by just using module_exists, you risk to run into errors like those:


if a site is still using an old version of a module, which doesn't have that function yet (so you shouldn't try to use it  yet).
if a site is already using an new version of a module, which doesn't have that function anymore (so you shouldn't try to use it  anymore).


My question: what are the typical criteria, or pros/cons, to decide for using either  module_exists versus function_exists?
You should always program to the API and not the implementation.  If Drupal provides a mechanism to do something, use it.

module_exists() should almost always be used for soft dependencies on something provided by a Drupal module.  You can always get version info, and decide what to do, using system_get_info().  There have been cases where functions are available when modules have been disabled (some of the class autoloader modules have has this problem).

function_exists() should be reserved for checking whether a PHP feature or library is available.  Core has some examples of this in some of the drupal_ wrappers for string manipulation and character set conversion.